From 3cd16c9d0fb334ddf18ae694a039d84e3e15ddc9 Mon Sep 17 00:00:00 2001 From: mkoch Date: Tue, 9 Jan 2024 17:28:28 +0300 Subject: [PATCH 1/6] extract data flow analysys part from live variable analysis --- sapfor/experts/Sapfor_2017/CMakeLists.txt | 7 + .../CFGraph/DataFlow/backward_data_flow.h | 108 ++++++ .../_src/CFGraph/DataFlow/data_flow.h | 161 +++++++++ .../_src/CFGraph/live_variable_analysis.cpp | 308 +++++------------- 4 files changed, 356 insertions(+), 228 deletions(-) create mode 100644 sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow.h create mode 100644 sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h diff --git a/sapfor/experts/Sapfor_2017/CMakeLists.txt b/sapfor/experts/Sapfor_2017/CMakeLists.txt index fd246f3..0ad33fe 100644 --- a/sapfor/experts/Sapfor_2017/CMakeLists.txt +++ b/sapfor/experts/Sapfor_2017/CMakeLists.txt @@ -218,6 +218,11 @@ set(CFG _src/CFGraph/IR.cpp _src/CFGraph/private_variables_analysis.h ) +set(DATA_FLOW + _src/CFGraph/DataFlow/data_flow.h + _src/CFGraph/DataFlow/backward_data_flow.h + ) + set(CREATE_INTER_T _src/CreateInterTree/CreateInterTree.cpp _src/CreateInterTree/CreateInterTree.h) @@ -377,6 +382,7 @@ set(ZLIB ${zlib_sources}/src/adler32.c set(SOURCE_EXE ${CFG} + ${DATA_FLOW} ${CREATE_INTER_T} ${DIRA} ${DISTR} @@ -406,6 +412,7 @@ set(SOURCE_EXE add_executable(Sapfor_F ${SOURCE_EXE}) source_group (CFGraph FILES ${CFG}) +source_group (CFGraph\\DataFlow FILES ${DATA_FLOW}) source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM}) source_group (Transformations\\CheckPoints FILES ${TR_CP}) 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 new file mode 100644 index 0000000..dd0b3c3 --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow.h @@ -0,0 +1,108 @@ +#pragma once +#include "data_flow.h" + +#include +#include +#include + +#include "../../Utils/SgUtils.h" +#include "../CFGraph.h" +#include "../IR.h" +#include "../RD_subst.h" + +template +class BackwardDataFlowAnalysis : public DataFlowAnalysis { + std::vector reorderSequence(const std::vector& blocks, + const std::set back_edge_sources); +public: + void fit(const std::vector& blocks); +}; + +// minimizes the number of blocks beween the ends of back edges +template +std::vector BackwardDataFlowAnalysis::reorderSequence(const std::vector& blocks, + const std::set back_edge_sources) +{ + std::vector res = { }; + + auto blocks_end = blocks.rend(); + for (auto it = blocks.rbegin(); it < blocks_end; it++) + { + SAPFOR::BasicBlock* curr = *it; + auto res_end = res.end(); + auto inserter = res.begin(); + if (back_edge_sources.count(curr) == 0) + { + auto curr_next_begin = curr->getNext().begin(); + auto curr_next_end = curr->getNext().end(); + while (inserter < res_end && std::find(curr_next_begin, curr_next_end, *inserter) == curr_next_end) + inserter++; + } + + res.insert(inserter, curr); + } + + return res; +} + +template +void BackwardDataFlowAnalysis::fit(const std::vector& blocks) +{ + std::set> back_edges = {}; + + bool returned = false; + std::map> back_edges_by_src; + + auto blocks_sorted = sortCfgNodes(blocks, &back_edges); + + std::set back_edge_sources; + + for (auto& edge : back_edges) + { + back_edges_by_src[edge.first].insert(edge.second); + back_edge_sources.insert(edge.first); + } + + back_edges.clear(); + + blocks_sorted = reorderSequence(blocks_sorted, back_edge_sources); + back_edge_sources.clear(); + + std::reverse(blocks_sorted.begin(), blocks_sorted.end()); + + nodes.clear(); + std::map node_by_block; + + for (auto block : blocks_sorted) + { + NodeType* node = createNode(block); + nodes.push_back(node); + node_by_block[block] = node; + } + + int nodes_size = nodes.size(); + + for (int i = 0; i < nodes_size; i++) + { + NodeType* node = nodes[i]; + + auto back_edges_by_src_it = back_edges_by_src.find(node->getBlock()); + if (back_edges_by_src_it != back_edges_by_src.end()) + { + // This node is a source for back edge + for (auto dest : back_edges_by_src_it->second) + { + auto node_by_block_it = node_by_block.find(dest); + if (node_by_block_it != node_by_block.end()) + node_by_block_it->second->getRollback().insert(i); + } + } + + for (auto next : node->getBlock()->getNext()) + { + auto node_by_block_it = node_by_block.find(next); + if (node_by_block_it != node_by_block.end()) + node->getPrevBlocks().insert(node_by_block_it->second); + } + } +} \ No newline at end of file diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h new file mode 100644 index 0000000..d4ac744 --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h @@ -0,0 +1,161 @@ +#pragma once +#include +#include + +#include "../../Utils/SgUtils.h" +#include "../CFGraph.h" +#include "../IR.h" + +enum +{ + CNT_NOTINIT = 0 +}; + +template +class DataFlowAnalysisNode { + int in_cnt = CNT_NOTINIT, out_cnt = CNT_NOTINIT; + + std::set rollback; + std::set ignore_rollback; + + std::set*> prev_blocks; + + SAPFOR::BasicBlock* bb; +public: + DataFlowAnalysisNode(); + + void doStep(); + + virtual DataType getIn() = 0; + virtual DataType getOut() = 0; + + virtual bool addIn(const DataType& data) = 0; + virtual bool addOut(const DataType& data) = 0; + + virtual bool forwardData(const DataType& data) = 0; + + bool newerThan(const DataFlowAnalysisNode* block) const { return out_cnt > block->in_cnt; } + + int getInCnt() { return in_cnt; } + int getOutCnt() { return out_cnt; } + + void setInCnt(int cnt) { in_cnt = cnt; } + void setOutCnt(int cnt) { out_cnt = cnt; } + + std::set& getRollback() { return rollback; } + std::set& getIgnoreRollback() { return ignore_rollback; } + + std::set*>& getPrevBlocks() { return prev_blocks; } + + SAPFOR::BasicBlock* getBlock() { return bb; } + void setBlock(SAPFOR::BasicBlock* b) { bb = b; } +}; + +template +class DataFlowAnalysis { +protected: + std::vector nodes; + + virtual NodeType* createNode(SAPFOR::BasicBlock* block) = 0; +public: + virtual void fit(const std::vector& blocks) = 0; + void analyze(); + + const std::vector& getNodes() { return nodes; } + + ~DataFlowAnalysis(); +}; + +template +DataFlowAnalysisNode::DataFlowAnalysisNode() { + getRollback() = {}; + getIgnoreRollback() = {}; + prev_blocks = {}; +} + +template +void DataFlowAnalysisNode::doStep() +{ + int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT; + for (auto next : prev_blocks) + { + if (in_cnt < next->out_cnt) + { + for (const auto& byOut : next->getOut()) + { + bool inserted = addIn({ byOut }); + + if (inserted) + { + if (next->out_cnt > in_max_cnt) + in_max_cnt = next->out_cnt; + + inserted = forwardData({ byOut }); + + if (inserted && next->out_cnt > out_max_cnt) + out_max_cnt = next->out_cnt; + } + } + } + } + + bool was_notinit = (out_cnt == CNT_NOTINIT); + + if (out_max_cnt != CNT_NOTINIT) + out_cnt = out_max_cnt; + + if (in_max_cnt != CNT_NOTINIT) + in_cnt = in_max_cnt; + + // TODO: fix counter overflow + if (was_notinit) + { + out_cnt++; + in_cnt++; + } +} + +template +void DataFlowAnalysis::analyze() { + auto curr = 0; + auto stop = nodes.size(); + + while (curr != stop) + { + auto curr_bb = nodes[curr]; + curr_bb->doStep(); + + const auto& jumps = curr_bb->getRollback(); + if (jumps.size() != 0) + { + auto& ignored_jumps = curr_bb->getIgnoreRollback(); + + bool jump = false; + for (const auto& jump_to : jumps) + { + if (ignored_jumps.insert(jump_to).second && curr_bb->newerThan(nodes[jump_to])) + { + jump = true; + curr = jump_to; + break; + } + } + + if (!jump) + curr_bb->getIgnoreRollback().clear(); + else + continue; + } + + curr++; + } +} + +template +DataFlowAnalysis::~DataFlowAnalysis() +{ + for (DataFlowAnalysisNode* node : nodes) + delete node; + + nodes.clear(); +} \ No newline at end of file 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 4b40ff9..3452e8e 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -1,5 +1,6 @@ #include "live_variable_analysis.h" #include "RD_subst.h" +#include "DataFlow/backward_data_flow.h" #include #include @@ -197,85 +198,67 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set& use, vector& formal_parameters, vector& fcalls, const map& funcByName); -enum -{ - CNT_NOTINIT = 0 +class LiveVarAnalysisNode : public DataFlowAnalysisNode>> { +private: + set live, dead; +public: + map> getIn() + { + return getBlock()->getLiveOut(); + }; + + map> getOut() + { + return getBlock()->getLiveIn(); + }; + + bool addIn(const map>& data) + { + return getBlock()->addLiveOut(data); + }; + + bool addOut(const map>& data) + { + return getBlock()->addLiveIn(data); + }; + + bool forwardData(const map>& data) + { + bool inserted = false; + + for (const auto& byArg : data) + if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end()) + inserted |= getBlock()->addLiveIn({ byArg }); + + return inserted; + }; + + LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector& formal_parameters, + vector& fcalls, const map& funcByName) + { + setBlock(block); + + buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName); + + for (SAPFOR::Argument* arg : live) + getBlock()->addLiveIn({ { arg, { getBlock() } } }); + } }; -struct BasicBlockNode -{ - SAPFOR::BasicBlock* bb; - set live, dead; - int in_cnt, out_cnt; - set next_blocks; +class LiveVarAnalysis : public BackwardDataFlowAnalysis>, LiveVarAnalysisNode> { +protected: + vector& formal_parameters; + vector& fcalls; + const map& funcByName; - set::reverse_iterator> rollback; - set::reverse_iterator> ignore_rollback; - - BasicBlockNode(SAPFOR::BasicBlock* block, vector& formal_parameters, - vector& fcalls, const map& funcByName) + LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override { - bb = block; - out_cnt = in_cnt = CNT_NOTINIT; - - buildUseDef(bb, live, dead, formal_parameters, fcalls, funcByName); - for (SAPFOR::Argument* arg : live) - bb->addLiveIn({ { arg, { bb } } }); - - rollback = {}; - ignore_rollback = {}; - next_blocks = {}; - } - - void updateLive() - { - bool in_changed = false, out_changed = false; - int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT; - for (auto next : next_blocks) - { - if (out_cnt < next->in_cnt) - { - for (const auto& byArg : next->bb->getLiveIn()) - { - bool inserted = bb->addLiveOut({ byArg }); - out_changed |= inserted; - - if (inserted) - { - if (next->in_cnt > out_max_cnt) - out_max_cnt = next->in_cnt; - - if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end()) - { - inserted = bb->addLiveIn({ byArg }); - if (inserted && next->in_cnt > in_max_cnt) - { - in_max_cnt = next->in_cnt; - in_changed = true; - } - } - } - } - } - } - - bool was_notinit = (in_cnt == CNT_NOTINIT); - - if (in_max_cnt != CNT_NOTINIT) - in_cnt = in_max_cnt; - - if (out_max_cnt != CNT_NOTINIT) - out_cnt = out_max_cnt; - - // TODO: fix counter overflow - if (was_notinit) - { - out_cnt++; - in_cnt++; - } - } - - bool newerThan(const BasicBlockNode* block) const { return in_cnt > block->out_cnt; } + return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName); + }; +public: + LiveVarAnalysis(vector& formal_parameters, vector& fcalls, + const map& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName) + { }; }; //Build use and def sets of block. Result are stored in use and def @@ -381,137 +364,6 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set& use, def = tmp_def; } -// minimizes the number of blocks beween the ends of back edges -static vector reorderSequence(const vector& blocks, - const set back_edge_sources) -{ - vector res = { }; - - auto blocks_end = blocks.rend(); - for (auto it = blocks.rbegin(); it < blocks_end; it++) - { - SAPFOR::BasicBlock* curr = *it; - auto res_end = res.end(); - auto inserter = res.begin(); - if (back_edge_sources.count(curr) == 0) - { - auto curr_next_begin = curr->getNext().begin(); - auto curr_next_end = curr->getNext().end(); - while (inserter < res_end && std::find(curr_next_begin, curr_next_end, *inserter) == curr_next_end) - inserter++; - } - - res.insert(inserter, curr); - } - - return res; -} - -// finds back edges, reorders and converts blocks into vector of BasicBlockNode* -// fills vector of formal parameters for given function -// fills info about arguments which becomes live after calls of functions -static vector toBlocksWithCnt(const vector& blocks, - vector& formal_parameters, - vector& fcalls, const map& funcByName) -{ - set> back_edges = {}; - - bool returned = false; - map> back_edges_by_src; - - auto blocks_sorted = sortCfgNodes(blocks, &back_edges); - - set back_edge_sources; - - for (auto& edge : back_edges) - { - back_edges_by_src[edge.first].insert(edge.second); - back_edge_sources.insert(edge.first); - } - - back_edges.clear(); - - blocks_sorted = reorderSequence(blocks_sorted, back_edge_sources); - back_edge_sources.clear(); - - vector blocks_with_counters; - map node_by_block; - for (auto block : blocks_sorted) - { - BasicBlockNode* node = new BasicBlockNode(block, formal_parameters, fcalls, funcByName); - blocks_with_counters.push_back(node); - node_by_block[block] = node; - } - - for (auto r_it = blocks_with_counters.rbegin(); r_it != blocks_with_counters.rend(); r_it++) - { - auto back_edges_by_src_it = back_edges_by_src.find((*r_it)->bb); - if (back_edges_by_src_it != back_edges_by_src.end()) - { - // This node is a source for back edge - for (auto dest : back_edges_by_src_it->second) - { - auto node_by_block_it = node_by_block.find(dest); - if (node_by_block_it != node_by_block.end()) - node_by_block_it->second->rollback.insert(r_it); - } - } - - for (auto next : (*r_it)->bb->getNext()) - { - auto node_by_block_it = node_by_block.find(next); - if (node_by_block_it != node_by_block.end()) - (*r_it)->next_blocks.insert(node_by_block_it->second); - } - } - - return blocks_with_counters; -} - -// iterate over separated subset of blocks -static void analyzeSequence(const vector& blocks_with_counters) -{ - auto curr = blocks_with_counters.rbegin(); - auto stop = blocks_with_counters.rend(); - - while (curr != stop) - { - auto curr_bb = *curr; - curr_bb->updateLive(); - - const auto& jumps = curr_bb->rollback; - if (jumps.size() != 0) - { - auto& ignored_jumps = curr_bb->ignore_rollback; - - bool jump = false; - for (const auto& jump_to : jumps) - { - if (ignored_jumps.insert(jump_to).second && curr_bb->newerThan(*jump_to)) - { - jump = true; - curr = jump_to; - break; - } - } - - if (!jump) - curr_bb->ignore_rollback.clear(); - else - continue; - } - - curr++; - } -} - -// delete all nodes from vector -static void freeBlocksWithCnt(const vector& blocks_with_counters) -{ - for (auto to_free : blocks_with_counters) - delete to_free; -} - // prints info about live variables void doDumpLive(const map>& CFGraph_for_project) { @@ -682,11 +534,11 @@ void runLiveVariableAnalysis(const map>& callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end()); funcByName[byFunc.first->funcName] = byFunc.first; } - + vector> scc; vector> callLvls = groupByCallDependencies(callDeps, scc); - map> func_to_blocks_with_cnt; + map func_to_analysis_object; map> func_to_parameters; list> live_for_fcalls; @@ -707,8 +559,9 @@ void runLiveVariableAnalysis(const map>& auto& params = func_to_parameters[byFunc->funcName] = vector(byFunc->funcParams.countOfPars, NULL); - auto& blocks_with_cnt = (func_to_blocks_with_cnt[byFunc->funcName] = toBlocksWithCnt(itCFG->second, params, curr_fcalls, funcByName)); - analyzeSequence(blocks_with_cnt); + LiveVarAnalysis* analysis_object = (func_to_analysis_object[byFunc->funcName] = new LiveVarAnalysis(params, curr_fcalls, funcByName)); + analysis_object->fit(itCFG->second); + analysis_object->analyze(); fillLiveDeadArgs(byFunc, itCFG->second); } @@ -728,7 +581,7 @@ void runLiveVariableAnalysis(const map>& auto it = assembled_fcalls.find(call.func); if (it == assembled_fcalls.end()) it = assembled_fcalls.insert({ call.func, fcall(call.func, call.block, {}) }).first; - + for (const auto& p : call.live_after) it->second.live_after[p.first].insert(p.second.begin(), p.second.end()); @@ -738,12 +591,12 @@ void runLiveVariableAnalysis(const map>& for (const auto& func : assembled_fcalls) { - auto func_it = func_to_blocks_with_cnt.find(func.first->funcName); - if (func_it == func_to_blocks_with_cnt.end()) + auto func_it = func_to_analysis_object.find(func.first->funcName); + if (func_it == func_to_analysis_object.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); auto param_it = func_to_parameters.find(func.first->funcName); - if(param_it == func_to_parameters.end()) + if (param_it == func_to_parameters.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); const vector& params = param_it->second; @@ -761,14 +614,14 @@ void runLiveVariableAnalysis(const map>& } } - set exits; + set exits; int max_cnt = CNT_NOTINIT; - for (auto block : func_it->second) + for (auto block : func_it->second->getNodes()) { - if (block->bb->getNext().size() == 0) + if (block->getBlock()->getNext().size() == 0) exits.insert(block); - if (block->out_cnt > max_cnt) - max_cnt = block->out_cnt; + if (block->getInCnt() > max_cnt) + max_cnt = block->getInCnt(); } max_cnt++; @@ -777,23 +630,22 @@ void runLiveVariableAnalysis(const map>& { for (const auto& byArg : live_after) { - if (exit->bb->addLiveOut({ byArg })) + if (exit->addIn({ byArg })) { - exit->out_cnt = max_cnt; - if (exit->live.find(byArg.first) == exit->live.end() && exit->dead.find(byArg.first) == exit->dead.end()) - if (exit->bb->addLiveIn({ byArg })) - exit->in_cnt = max_cnt; + exit->setInCnt(max_cnt); + if (exit->forwardData({ byArg })) + exit->setOutCnt(max_cnt); } } } - + // now we can update live sets in all blocks - analyzeSequence(func_it->second); + func_it->second->analyze(); } } - for (const auto& nodeByFunc : func_to_blocks_with_cnt) - freeBlocksWithCnt(nodeByFunc.second); + for (const auto& byFunc : func_to_analysis_object) + delete byFunc.second; for (auto& byFunc : CFGraph_for_project) for (auto& byBlock : byFunc.second) -- 2.49.1 From 5f8940f34d032a593ed913be4cbcc9e1cd7ec354 Mon Sep 17 00:00:00 2001 From: mkoch Date: Tue, 9 Jan 2024 18:13:56 +0300 Subject: [PATCH 2/6] reorganize live variable analysis to use it's functions further --- .../_src/CFGraph/live_variable_analysis.cpp | 351 ++++++++++-------- .../_src/CFGraph/live_variable_analysis.h | 35 ++ 2 files changed, 227 insertions(+), 159 deletions(-) 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 3452e8e..ba8a0ae 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -17,6 +17,8 @@ using std::set; using std::unordered_map; using std::list; +using LIVE_VARIABLES::fcall; + namespace SAPFOR { bool BasicBlock::addLive(const map>& to_add, bool in) { @@ -28,7 +30,7 @@ namespace SAPFOR { const set& add_in_live = byNew.second; set new_in_live = {}; - + auto current_set_iter = current_set.find(byNew.first); if (current_set_iter == current_set.end()) @@ -106,7 +108,7 @@ namespace SAPFOR return res; } - + void BasicBlock::compressLives() { for (auto& bySrc : { &live_in, &live_out, &live_inout }) for (auto& byArg : *bySrc) @@ -114,89 +116,77 @@ namespace SAPFOR } } -struct fcall +bool fcall::tryInsert(set& dest, SAPFOR::BasicBlock* b) { -private: - bool tryInsert(set& dest, SAPFOR::BasicBlock* b) + if (b == block || dest.find(block) == dest.end()) { - if (b == block || dest.find(block) == dest.end()) - { - dest.insert(b); - return true; - } - - return false; + dest.insert(b); + return true; } -public: - FuncInfo* func; - - map> live_after; - set dead_after; + return false; +} - map> commons_live_after; - set commons_dead_after; +fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector& p) +{ + block = b; + func = f; - vector params; - SAPFOR::BasicBlock* block; + int param_size = p.size(); + params = vector(param_size, NULL); - fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector& p) - { - block = b; - func = f; - - int param_size = p.size(); - params = vector(param_size, NULL); + for (int i = 0; i < param_size; i++) + if (f->funcParams.isArgOut(i)) + params[i] = p[i]; +} - for (int i = 0; i < param_size; i++) - if (f->funcParams.isArgOut(i)) - params[i] = p[i]; +void fcall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) +{ + if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) + { + if (commons_dead_after.find(arg) == commons_dead_after.end()) + tryInsert(commons_live_after[arg], b); } - void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) + auto it = find(params.begin(), params.end(), arg); + if (it != params.end()) { - if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) - { - if (commons_dead_after.find(arg) == commons_dead_after.end()) - tryInsert(commons_live_after[arg], b); - } - - auto it = find(params.begin(), params.end(), arg); - if (it != params.end()) - { - int idx = it - params.begin(); - if (dead_after.find(idx) == dead_after.end()) - tryInsert(live_after[idx], b); - } + int idx = it - params.begin(); + if (dead_after.find(idx) == dead_after.end()) + tryInsert(live_after[idx], b); } +} - void make_dead(SAPFOR::Argument* arg) +void fcall::make_dead(SAPFOR::Argument* arg) +{ + if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) { - if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) + if (commons_live_after.find(arg) == commons_live_after.end()) commons_dead_after.insert(arg); - - auto it = find(params.begin(), params.end(), arg); - if (it != params.end()) - { - int idx = it - params.begin(); - dead_after.insert(idx); - } } - void updateFromOut() + auto it = find(params.begin(), params.end(), arg); + if (it != params.end()) { - for (const auto& p : block->getLiveOut()) - for (auto b : p.second) - make_live(p.first, b); + int idx = it - params.begin(); + if (live_after.find(idx) == live_after.end()) + dead_after.insert(idx); } -}; +} + +void fcall::updateFromOut() +{ + for (const auto& p : block->getLiveOut()) + for (auto b : p.second) + make_live(p.first, b); +} static bool getLiveDead(const vector& params, const string& func_name, set& live, set& dead); static void buildUseDef(SAPFOR::BasicBlock* block, set& use, set& def, - vector& formal_parameters, vector& fcalls, - const map& funcByName); + vector& formal_parameters, vector& fcalls, + const map& funcByName, bool interprocedural); class LiveVarAnalysisNode : public DataFlowAnalysisNode>> { private: @@ -234,11 +224,11 @@ public: }; LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector& formal_parameters, - vector& fcalls, const map& funcByName) + vector& fcalls, const map& funcByName) { setBlock(block); - buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName); + buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true); for (SAPFOR::Argument* arg : live) getBlock()->addLiveIn({ { arg, { getBlock() } } }); @@ -251,8 +241,7 @@ protected: vector& fcalls; const map& funcByName; - LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override - { + LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override { return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName); }; public: @@ -261,107 +250,151 @@ public: { }; }; -//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& fcalls, - const map& funcByName) +void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, + set& use, set& def, + vector& formal_parameters, vector& fcalls, + vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, + string& fName, const map& funcByName, bool interprocedural) { - set tmp_use, tmp_def; + for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() }) + if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_) + formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg; - vector lastParamRef; - bool fcall_added; + SAPFOR::Argument* res_arg = NULL; - for (auto ir_block : block->getInstructions()) + static const set skip = { SAPFOR::CFG_OP::ENTRY }; + SAPFOR::CFG_OP instr_operation = instr->getOperation(); + if (hasStoreStructure(instr_operation)) { - fcall_added = false; - SAPFOR::Instruction* instr = ir_block->getInstruction(); - for (auto arg : { instr->getArg1(), instr->getArg2(), instr->getResult() }) - if (arg && arg->getMemType() == SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_) - formal_parameters[getParamIndex(arg, formal_parameters.size())] = arg; + res_arg = instr->getArg1(); + set instr_args = { instr->getResult(), instr->getArg2() }; + use.insert(instr_args.begin(), instr_args.end()); + } + else if (instr_operation == SAPFOR::CFG_OP::PARAM) + { + lastParamRef[last_param_ref_index--] = instr->getArg1(); + } + else if (instr_operation == SAPFOR::CFG_OP::F_CALL) + { + res_arg = instr->getResult(); - set res = {}, args = {}; - SAPFOR::Argument* res_arg = NULL; + last_param_ref_size = stoi(instr->getArg2()->getValue()); - static const set skip = { SAPFOR::CFG_OP::ENTRY }; - SAPFOR::CFG_OP instr_operation = instr->getOperation(); - if (hasStoreStructure(instr_operation)) { - res_arg = instr->getArg1(); - std::set instr_args = { instr->getResult(), instr->getArg2()}; - insertIfVar(instr_args.begin(), instr_args.end(), args); - } - else if (instr_operation == SAPFOR::CFG_OP::PARAM) - lastParamRef.push_back(instr->getArg1()); - else if (instr_operation == SAPFOR::CFG_OP::F_CALL) + lastParamRef.clear(); + lastParamRef.resize(last_param_ref_size); + + last_param_ref_index = last_param_ref_size - 1; + + fName = instr->getArg1()->getValue(); + } + else if (skip.find(instr_operation) == skip.end()) + { + //default + res_arg = instr->getResult(); + std::set intr_args = { instr->getArg1(), instr->getArg2() }; + use.insert(intr_args.begin(), intr_args.end()); + } + else + { + //skip + return; + } + + 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()) { - res_arg = instr->getResult(); + fcalls.push_back(fcall(func_it->second, block, lastParamRef)); - int count = stoi(instr->getArg2()->getValue()); - if (lastParamRef.size() != count) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + auto r_it = fcalls.rbegin(); + auto r_end = fcalls.rend(); - const string& fName = instr->getArg1()->getValue(); - auto func_it = funcByName.find(fName); - if (func_it != funcByName.end()) - { - fcalls.push_back(fcall(func_it->second, block, lastParamRef)); - fcall_added = true; - } - - set make_live, make_dead; - if (fName == "_READ") - res.insert(lastParamRef.begin(), lastParamRef.end()); - else if (getLiveDead(lastParamRef, fName, make_live, make_dead)) - { - insertIfVar(make_live.begin(), make_live.end(), args); - insertIfVar(make_dead.begin(), make_dead.end(), res); - } - else - insertIfVar(lastParamRef.begin(), lastParamRef.end(), args); - - lastParamRef.clear(); - } - else if(skip.find(instr_operation) == skip.end()) - { - //default - res_arg = instr->getResult(); - std::set intr_args = { instr->getArg1(), instr->getArg2() }; - insertIfVar(intr_args.begin(), intr_args.end(), args); - } - else { - //skip - continue; - } - - if (res_arg && res_arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR) - res.insert(res_arg); - - for (auto e : args) - if (!tmp_def.count(e)) - tmp_use.insert(e); - - for(auto e : res) - if (!tmp_use.count(e)) - tmp_def.insert(e); - - auto r_it = fcalls.rbegin(); - auto r_end = fcalls.rend(); - if (fcall_added && r_it != r_end) - r_it++; - - while (r_it != r_end && r_it->block == block) - { - for (auto e : args) - r_it->make_live(e, block); - - for (auto e : res) + for (auto e : def) r_it->make_dead(e); - r_it++; + for (auto e : use) + r_it->make_live(e, block); + } + + set make_live, make_dead; + if (fName == "_READ") + def.insert(lastParamRef.begin(), lastParamRef.end()); + else if (interprocedural && getLiveDead(lastParamRef, fName, make_live, make_dead)) + { + use.insert(make_live.begin(), make_live.end()); + def.insert(make_dead.begin(), make_dead.end()); + } + else + use.insert(lastParamRef.begin(), lastParamRef.end()); + + last_param_ref_index = 0; + last_param_ref_size = 0; + + lastParamRef.clear(); + fName = ""; + } + + if (res_arg) + def.insert(res_arg); +} + +static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, + set& use, set& def, + vector& formal_parameters, vector& fcalls, + vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, + string& fName, const map& funcByName, bool interprocedural) +{ + set res, args; + + getUseDefForInstruction(block, instr, + args, res, + formal_parameters, fcalls, + lastParamRef, last_param_ref_index, last_param_ref_size, + fName, funcByName, + interprocedural + ); + + for (auto e : res) + { + if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + { + def.insert(e); + use.erase(e); } } - use = tmp_use; - def = tmp_def; + for (auto e : args) + { + if (e && e->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + { + use.insert(e); + def.erase(e); + } + } +} + +//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& fcalls, + const map& funcByName, bool interprocedural) +{ + vector lastParamRef; + int last_param_ref_index = 0, last_param_ref_size = 0; + string fName; + + const auto& instructions = block->getInstructions(); + auto ir_block_it = instructions.rbegin(), ir_block_end = instructions.rend(); + + for (; ir_block_it != ir_block_end; ir_block_it++) + { + updateUseDefForInstruction(block, (*ir_block_it)->getInstruction(), + use, def, + formal_parameters, fcalls, + lastParamRef, last_param_ref_index, last_param_ref_size, + fName, funcByName, + interprocedural + ); + } } // prints info about live variables @@ -379,7 +412,7 @@ void doDumpLive(const map>& CFGraph_for_p for (const auto& live : byBB->getLiveIn()) { __spf_print(1, " %s:", live.first->getValue().c_str()); - for(auto use : live.second) + for (auto use : live.second) __spf_print(1, " %d", use->getNumber()); __spf_print(1, "\n"); } @@ -482,8 +515,8 @@ static void fillLiveDeadArgs(const FuncInfo* func, const vector& params, - const map, set>>& params_and_globals, - const string& func_name, set& result) + const map, set>>& params_and_globals, + const string& func_name, set& result) { auto globals_it = params_and_globals.find(func_name); @@ -498,7 +531,7 @@ bool joinGlobalsWithParameters(const vector& params, for (int idx : param_indexes) { if (idx < params_size) { - if(params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + if (params[idx] && params[idx]->getType() == SAPFOR::CFG_ARG_TYPE::VAR) result.insert(params[idx]); } else @@ -510,11 +543,11 @@ bool joinGlobalsWithParameters(const vector& params, } // fill sets of arguments wich becomes live or dead after call with parameters params -static bool getLiveDead(const vector& params, const string& func_name, - set& live, set& dead) +static bool getLiveDead(const vector& params, const string& func_name, + set& live, set& dead) { return joinGlobalsWithParameters(params, live_by_func, func_name, live) && - joinGlobalsWithParameters(params, dead_by_func, func_name, dead); + joinGlobalsWithParameters(params, dead_by_func, func_name, dead); } // entrypoint for live variable analysis pass diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h index 52e183b..a697273 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h @@ -1,6 +1,35 @@ +#pragma once + #include "../Utils/SgUtils.h" #include "CFGraph.h" +namespace LIVE_VARIABLES +{ + struct fcall + { + private: + bool tryInsert(std::set& dest, SAPFOR::BasicBlock* b); + public: + FuncInfo* func; + + std::map> live_after; + std::set dead_after; + + std::map> commons_live_after; + std::set commons_dead_after; + + std::vector params; + SAPFOR::BasicBlock* block; + + fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector& p); + + void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b); + void make_dead(SAPFOR::Argument* arg); + + void updateFromOut(); + }; +} + template void insertIfVar(IT begin, IT end, DEST& to) { for (auto it = begin; it != end; it++) @@ -8,6 +37,12 @@ void insertIfVar(IT begin, IT end, DEST& to) { to.insert(*it); }; +void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, + std::set& use, std::set& def, + std::vector& formal_parameters, std::vector& fcalls, + std::vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, + std::string& fName, const std::map& funcByName, bool interprocedural); + void runLiveVariableAnalysis(const std::map>& CFGraph_for_project); void doDumpLive(const std::map>& CFGraph_for_project); -- 2.49.1 From 14219cdfd58e96cb6d34f086d7a25de115739d29 Mon Sep 17 00:00:00 2001 From: mkoch Date: Tue, 9 Jan 2024 18:28:50 +0300 Subject: [PATCH 3/6] add REMOVE_DEAD_CODE_AND_UNPARSE (debug) pass --- sapfor/experts/Sapfor_2017/CMakeLists.txt | 6 +- .../Sapfor_2017/_src/CFGraph/CFGraph.h | 4 + .../_src/CFGraph/live_variable_analysis.cpp | 31 ++ sapfor/experts/Sapfor_2017/_src/Sapfor.cpp | 8 + sapfor/experts/Sapfor_2017/_src/Sapfor.h | 2 + .../_src/Transformations/dead_code.cpp | 436 ++++++++++++++++++ .../_src/Transformations/dead_code.h | 14 + .../Sapfor_2017/_src/Utils/PassManager.h | 2 + 8 files changed, 502 insertions(+), 1 deletion(-) create mode 100644 sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp create mode 100644 sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h diff --git a/sapfor/experts/Sapfor_2017/CMakeLists.txt b/sapfor/experts/Sapfor_2017/CMakeLists.txt index 0ad33fe..94433f2 100644 --- a/sapfor/experts/Sapfor_2017/CMakeLists.txt +++ b/sapfor/experts/Sapfor_2017/CMakeLists.txt @@ -160,7 +160,9 @@ set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp _src/ParallelizationRegions/expand_extract_reg.h _src/ParallelizationRegions/resolve_par_reg_conflicts.cpp _src/ParallelizationRegions/resolve_par_reg_conflicts.h) - + +set(TR_DEAD_CODE _src/Transformations/dead_code.cpp + _src/Transformations/dead_code.h) set(TR_CP _src/Transformations/checkpoints.cpp _src/Transformations/checkpoints.h) set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp @@ -191,6 +193,7 @@ set(TR_CONV _src/Transformations/convert_to_c.cpp _src/Transformations/convert_to_c.h) set(TRANSFORMS + ${TR_DEAD_CODE} ${TR_CP} ${TR_VECTOR} ${TR_ENDDO_LOOP} @@ -414,6 +417,7 @@ add_executable(Sapfor_F ${SOURCE_EXE}) source_group (CFGraph FILES ${CFG}) source_group (CFGraph\\DataFlow FILES ${DATA_FLOW}) +source_group (Transformations\\DeadCodeRemoving FILES ${TR_DEAD_CODE}) source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM}) source_group (Transformations\\CheckPoints FILES ${TR_CP}) source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP}) diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h index 99b98dd..dbe790d 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h @@ -33,6 +33,7 @@ namespace SAPFOR bool addLive(const std::map>& to_add, bool in); std::map> getLive(bool in) const; + bool removeLive(SAPFOR::Argument* to_remove, bool in); public: BasicBlock() { num = lastNumBlock++; } BasicBlock(IR_Block* item); @@ -71,6 +72,9 @@ namespace SAPFOR */ bool addLiveIn(const std::map>& to_add) { return addLive(to_add, true); }; bool addLiveOut(const std::map>& to_add) { return addLive(to_add, false); }; + + bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); }; + bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); }; std::map> getLiveIn() const { return getLive(true); }; std::map> getLiveOut() const { return getLive(false); }; 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 ba8a0ae..ccd933e 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -97,6 +97,37 @@ namespace SAPFOR return inserted; }; + bool BasicBlock::removeLive(SAPFOR::Argument* to_remove, bool in) + { + std::map>& current_set = (in ? live_in : live_out); + std::map>& opposite_set = (!in ? live_in : live_out); + + bool removed = false; + + removed |= (current_set.erase(to_remove) != 0); + + if (!removed) + { + auto it = live_inout.find(to_remove); + + if (it != live_inout.end()) + { + auto& dest = opposite_set[to_remove]; + for (SAPFOR::BasicBlock* bb : it->second) + { + auto find_bb_from_dest = std::lower_bound(dest.begin(), dest.end(), bb); + + if (find_bb_from_dest == dest.end() || *find_bb_from_dest != bb) + dest.insert(find_bb_from_dest, bb); + } + + removed = true; + } + } + + return removed; + }; + map> BasicBlock::getLive(bool in) const { auto& current_set = in ? live_in : live_out; diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp index f64f5e8..4a006d0 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp @@ -79,6 +79,7 @@ #include "Transformations/private_removing.h" #include "Transformations/fix_common_blocks.h" #include "Transformations/convert_to_c.h" +#include "Transformations/dead_code.h" #include "RenameSymbols/rename_symbols.h" #include "ProjectParameters/projectParameters.h" @@ -1169,6 +1170,12 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne covertToC(file); else if (curr_regime == INSERT_NO_DISTR_FLAGS_FROM_GUI) addPrivatesToArraysFromGUI(file, declaredArrays, distrStateFromGUI); + else if (curr_regime == REMOVE_DEAD_CODE_AND_UNPARSE) + { + auto funcsForFile = getObjectForFileFromMap(file_name, allFuncInfo_IR); + for (auto& func : funcsForFile) + removeDeadCode(func->funcPointer, allFuncInfo_IR, commonBlocks); + } else if (curr_regime == TEST_PASS) { //test pass @@ -2515,6 +2522,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam findFunctionsToInclude(true); break; // all these cases run UNPARSE_FILE after + case REMOVE_DEAD_CODE_AND_UNPARSE: case RENAME_SYMBOLS: case RESOLVE_PAR_REGIONS: case CREATE_PARALLEL_REGIONS: diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.h b/sapfor/experts/Sapfor_2017/_src/Sapfor.h index 670cd9c..a66f577 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.h +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.h @@ -165,6 +165,7 @@ enum passes { BUILD_IR, LIVE_ANALYSIS_IR, PRIVATE_ANALYSIS_IR, + REMOVE_DEAD_CODE_AND_UNPARSE, FIX_COMMON_BLOCKS, REMOVE_OMP_DIRS, @@ -343,6 +344,7 @@ static void setPassValues() passNames[CALL_GRAPH_IR] = "CALL_GRAPH_IR"; passNames[LIVE_ANALYSIS_IR] = "LIVE_ANALYSIS_IR"; passNames[PRIVATE_ANALYSIS_IR] = "PRIVATE_ANALYSIS_IR"; + passNames[REMOVE_DEAD_CODE_AND_UNPARSE] = "REMOVE_DEAD_CODE_AND_UNPARSE"; passNames[FIX_COMMON_BLOCKS] = "FIX_COMMON_BLOCKS"; passNames[REMOVE_OMP_DIRS] = "REMOVE_OMP_DIRS"; diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp new file mode 100644 index 0000000..3c9c548 --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp @@ -0,0 +1,436 @@ +#include "dead_code.h" + +#include +#include +#include +#include + +using std::map; +using std::string; +using std::vector; +using std::set; + +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, + 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, {}, + false + ); + + if (!useful) + { + for (SAPFOR::Argument* r : res) + { + if (use.find(r) != use.end() || r->getMemType() != SAPFOR::CFG_MEM_TYPE::LOCAL_) + { + useful = true; + break; + } + } + } + + if (!useful) + { + set always_useful = + { + SAPFOR::CFG_OP::POINTER_ASS, + SAPFOR::CFG_OP::STORE, + SAPFOR::CFG_OP::REC_REF_STORE, + SAPFOR::CFG_OP::RANGE, + 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 + }; + + if (always_useful.find(instr->getOperation()) != always_useful.end()) + useful = true; + else if(instr->getOperation() == SAPFOR::CFG_OP::PARAM && last_fcall_useful) + useful = true; + } + + if (useful) + { + if (instr->getOperation() == SAPFOR::CFG_OP::F_CALL) + last_fcall_useful = true; + + for (auto e : res) + { + def.insert(e); + use.erase(e); + } + + for (auto e : args) + { + use.insert(e); + def.erase(e); + } + + insertIfVar(args.begin(), args.end(), usedByThisBlock); + } +} + + +//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 use_with_regs = use, def_with_regs = def; + + vector lastParamRef; + int last_param_ref_index = 0, last_param_ref_size = 0; + string fName = ""; + bool last_fcall_useful = false; + + const auto& instructions = block->getInstructions(); + int instr_size = instructions.size(); + + for (int i = instr_size - 1; i >= 0; i--) + { + bool u = useful[i]; + + updateUseDefForInstruction(block, instructions[i]->getInstruction(), + use_with_regs, def_with_regs, + formal_parameters, + lastParamRef, last_param_ref_index, last_param_ref_size, + fName, + u, last_fcall_useful, + usedByThisBlock + ); + + useful[i] = u; + } + + insertIfVar(use_with_regs.begin(), use_with_regs.end(), use); + insertIfVar(def_with_regs.begin(), def_with_regs.end(), def); +} + + +class DeadCodeAnalysisNode : public DataFlowAnalysisNode>> { +private: + vector useful; + bool useful_block = false; + set next_notempty_in, next_notempty_out; + bool useful_jump = false; + + vector& formal_parameters; +public: + bool updateJumpStatus() + { + bool res = false; + const auto& prev = getPrevBlocks(); + if (prev.size() > 1 && !useful.back() && + getBlock()->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF) + { + const auto& example = dynamic_cast(*prev.begin())->next_notempty_out; + + for (auto p : prev) + { + DeadCodeAnalysisNode* next = dynamic_cast(p); + + if (next->next_notempty_out != example) + { + useful.back() = true; + res = true; + break; + } + } + } + + return res; + } + + bool updateNextNotEmpty() + { + bool updated = false; + + if(!useful_block) + { + set current = {}; + + for (auto nextP : getPrevBlocks()) + { + DeadCodeAnalysisNode* next = dynamic_cast(nextP); + + if(!next) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + current.insert(next->next_notempty_out.begin(), next->next_notempty_out.end()); + } + + if (current != next_notempty_in) + { + next_notempty_in = current; + updated = true; + } + } + + return updated; + } + + map> getIn() { + return getBlock()->getLiveOut(); + }; + + 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 addOut(const map>& data) { + return getBlock()->addLiveIn(data); + }; + + bool forwardData(const map>& data) { + bool inserted = false; + SAPFOR::BasicBlock* bb= getBlock(); + + set use, def; + + for (const auto& byArg : data) + use.insert(byArg.first); + + set usedByThisBlock; + buildUseDef(bb, use, def, this->formal_parameters, useful, usedByThisBlock); + + auto in = bb->getLiveIn(), out = bb->getLiveOut(); + + for (SAPFOR::Argument* arg : use) + { + bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end(); + + if (!this_block) + { + 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(!useful_block) + { + for(bool status : useful) + { + if (status) + { + useful_block = true; + + inserted = true; + next_notempty_out = { this }; + break; + } + } + } + + if (!useful_block) + { + if (next_notempty_in != next_notempty_out) + { + inserted = true; + next_notempty_out = next_notempty_in; + } + } + + return inserted; + }; + + DeadCodeAnalysisNode(SAPFOR::BasicBlock* block, vector& formal_parameters) : + formal_parameters(formal_parameters) + { + setBlock(block); + useful.resize(block->getInstructions().size(), false); + set use, def; + set usedByThisBlock; + + buildUseDef(getBlock(), use, def, this->formal_parameters, useful, usedByThisBlock); + + for (SAPFOR::Argument* arg : use) + getBlock()->addLiveIn({ { arg, { getBlock() } } }); + } + + const vector& getResult() { return useful; }; +}; + +class DeadCodeAnalysis : public BackwardDataFlowAnalysis>, DeadCodeAnalysisNode> { +protected: + vector& formal_parameters; + + DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override { + return new DeadCodeAnalysisNode(block, formal_parameters); + }; +public: + DeadCodeAnalysis(vector& formal_parameters) : + formal_parameters(formal_parameters) + { }; +}; + + +void removeDeadCode(SgStatement* func, + const map>& allFuncs, + const map& commonBlocks) +{ + SgProgHedrStmt* prog = isSgProgHedrStmt(func); + + if (prog) + __spf_print(1, "[analyze %s]\n", prog->name().identifier()); + else + __spf_print(1, "[cannot resolve name of function]\n"); + + + auto cfg = buildCFGforCurrentFunc(func, SAPFOR::CFG_Settings(true, false, false, false, false, false, false), commonBlocks, allFuncs); + + if(cfg.size() != 1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + const auto& cfg_pair = *(cfg.begin()); + + vector func_parameters(cfg_pair.first->funcParams.countOfPars, NULL); + + DeadCodeAnalysis* analysis_object = new DeadCodeAnalysis(func_parameters); + + analysis_object->fit(cfg_pair.second); + analysis_object->analyze(); + + set useful; + + for (DeadCodeAnalysisNode* byNode : analysis_object->getNodes()) + { + const auto& instructions = byNode->getBlock()->getInstructions(); + const auto& statuses = byNode->getResult(); + + int size = instructions.size(); + + if(size != statuses.size()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (int i = 0; i < size; i++) + { + if(statuses[i]) + { + SgStatement* stmt = instructions[i]->getInstruction()->getOperator(); + + while(stmt && useful.insert(stmt).second) + { + __spf_print(1, "[Useful statement '%s' on line %d]\n", stmt->unparse(), stmt->lineNumber()); + stmt = stmt->controlParent(); + } + } + } + } + + SgStatement* end = func->lastNodeOfStmt(), *st = func; + + set removable = + { + ASSIGN_STAT + }; + + SgStatement* enclosing = st->controlParent(); + SgStatement* encl_end = enclosing ? enclosing->lastNodeOfStmt() : NULL; + + while (st != end) + { + SgStatement* next = st->lexNext(); + SgStatement* parent = NULL; + + if (removable.find(st->variant()) != removable.end() && useful.find(st) == useful.end()) + { + __spf_print(1, "[Useless statement '%s' on line %d]\n", st->unparse(), st->lineNumber()); + + parent = st->controlParent(); + + st->extractStmt()->deleteStmt(); + st = NULL; + } + else + { + if (st == encl_end) + { + if (enclosing) + { + bool empty_parent = false; + + switch (enclosing->variant()) + { + case IF_NODE: + empty_parent = + enclosing->lexNext() == encl_end || // IF THEN ENDIF + enclosing->lexNext()->variant() == CONTROL_END && + enclosing->lexNext()->lexNext() == encl_end; // IF THEN ELSE ENDIF + break; + default: + empty_parent = enclosing->lexNext() == encl_end; + break; + } + + if(empty_parent) + { + parent = enclosing->controlParent(); + enclosing->extractStmt()->deleteStmt(); + st->extractStmt()->deleteStmt(); + st = NULL; + } + } + + } + } + + if(!parent) + parent = st->controlParent(); + + if (parent != enclosing) + { + enclosing = parent; + encl_end = enclosing ? enclosing->lastNodeOfStmt() : NULL; + } + + st = next; + } +} \ No newline at end of file diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h new file mode 100644 index 0000000..7c83b1d --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +#include "../Utils/SgUtils.h" +#include "../CFGraph/CFGraph.h" +#include "../CFGraph/live_variable_analysis.h" +#include "../CFGraph/DataFlow/data_flow.h" +#include "../CFGraph/DataFlow/backward_data_flow.h" + +void removeDeadCode(SgStatement* func, + const std::map>&allFuncs, + const std::map& commonBlocks); \ No newline at end of file diff --git a/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h b/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h index 3e68a6a..88ed1ba 100644 --- a/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h +++ b/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h @@ -306,6 +306,8 @@ void InitPassesDependencies(map> &passDepsIn, set Pass(REMOVE_OMP_DIRS) <= Pass(REMOVE_OMP_DIRS_TRANSFORM); + Pass(BUILD_IR) <= 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, REVERSE_CREATED_NESTED_LOOPS, PREDICT_SCHEME, CALCULATE_STATS_SCHEME, REVERT_SPF_DIRS, CLEAR_SPF_DIRS, TRANSFORM_SHADOW_IF_FULL, -- 2.49.1 From bd8690d54ada5776728dbb7df94010c196cdab01 Mon Sep 17 00:00:00 2001 From: mkoch Date: Wed, 10 Jan 2024 16:20:48 +0300 Subject: [PATCH 4/6] Live variable analysis: use vectors of blocks instead of sets --- .../Sapfor_2017/_src/CFGraph/CFGraph.h | 12 +++--- .../_src/CFGraph/live_variable_analysis.cpp | 38 +++++++++++-------- .../_src/Transformations/dead_code.cpp | 14 +++---- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h index dbe790d..e47447c 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/CFGraph.h @@ -31,8 +31,8 @@ namespace SAPFOR //live variables [arg -> blocks with usages] std::map> live_in, live_out, live_inout; - bool addLive(const std::map>& to_add, bool in); - std::map> getLive(bool in) const; + bool addLive(const std::map>& to_add, bool in); + std::map> getLive(bool in) const; bool removeLive(SAPFOR::Argument* to_remove, bool in); public: BasicBlock() { num = lastNumBlock++; } @@ -70,14 +70,14 @@ namespace SAPFOR /* * FOR LIVE ANALYSIS */ - bool addLiveIn(const std::map>& to_add) { return addLive(to_add, true); }; - bool addLiveOut(const std::map>& to_add) { return addLive(to_add, false); }; + bool addLiveIn(const std::map>& to_add) { return addLive(to_add, true); }; + bool addLiveOut(const std::map>& to_add) { return addLive(to_add, false); }; bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); }; bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); }; - std::map> getLiveIn() const { return getLive(true); }; - std::map> getLiveOut() const { return getLive(false); }; + std::map> getLiveIn() const { return getLive(true); }; + std::map> getLiveOut() const { return getLive(false); }; void compressLives(); /* 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 ccd933e..0836b52 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -21,15 +21,15 @@ using LIVE_VARIABLES::fcall; namespace SAPFOR { - bool BasicBlock::addLive(const map>& to_add, bool in) { + bool BasicBlock::addLive(const map>& to_add, bool in) { std::map>& current_set = (in ? live_in : live_out); std::map>& opposite_set = (!in ? live_in : live_out); bool inserted = false; for (const auto& byNew : to_add) { - const set& add_in_live = byNew.second; - set new_in_live = {}; + const vector& add_in_live = byNew.second; + vector new_in_live = {}; auto current_set_iter = current_set.find(byNew.first); @@ -128,14 +128,19 @@ namespace SAPFOR return removed; }; - map> BasicBlock::getLive(bool in) const { + map> BasicBlock::getLive(bool in) const { auto& current_set = in ? live_in : live_out; - map> res; + map> res; for (auto& by_source : { current_set, live_inout }) + { for (auto& by_pair : by_source) - res[by_pair.first].insert(by_pair.second.begin(), by_pair.second.end()); + { + auto& dest = res[by_pair.first]; + dest.insert(dest.end(), by_pair.second.begin(), by_pair.second.end()); + } + } return res; } @@ -219,31 +224,31 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set& use, vector& formal_parameters, vector& fcalls, const map& funcByName, bool interprocedural); -class LiveVarAnalysisNode : public DataFlowAnalysisNode>> { +class LiveVarAnalysisNode : public DataFlowAnalysisNode>> { private: set live, dead; public: - map> getIn() + map> getIn() { return getBlock()->getLiveOut(); }; - map> getOut() + map> getOut() { return getBlock()->getLiveIn(); }; - bool addIn(const map>& data) + 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 forwardData(const map>& data) { bool inserted = false; @@ -266,7 +271,7 @@ public: } }; -class LiveVarAnalysis : public BackwardDataFlowAnalysis>, LiveVarAnalysisNode> { +class LiveVarAnalysis : public BackwardDataFlowAnalysis>, LiveVarAnalysisNode> { protected: vector& formal_parameters; vector& fcalls; @@ -694,10 +699,13 @@ void runLiveVariableAnalysis(const map>& { for (const auto& byArg : live_after) { - if (exit->addIn({ byArg })) + map> converted; + converted[byArg.first] = vector(byArg.second.begin(), byArg.second.end()); + + if (exit->addIn(converted)) { exit->setInCnt(max_cnt); - if (exit->forwardData({ byArg })) + if (exit->forwardData(converted)) exit->setOutCnt(max_cnt); } } diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp index 3c9c548..9280ecd 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp @@ -126,7 +126,7 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set& use, } -class DeadCodeAnalysisNode : public DataFlowAnalysisNode>> { +class DeadCodeAnalysisNode : public DataFlowAnalysisNode>> { private: vector useful; bool useful_block = false; @@ -188,15 +188,15 @@ public: return updated; } - map> getIn() { + map> getIn() { return getBlock()->getLiveOut(); }; - map> getOut() { + map> getOut() { return getBlock()->getLiveIn(); }; - bool addIn(const map>& data) { + bool addIn(const map>& data) { bool inserted = getBlock()->addLiveOut(data); if (!useful_block) @@ -207,11 +207,11 @@ public: return inserted; }; - bool addOut(const map>& data) { + bool addOut(const map>& data) { return getBlock()->addLiveIn(data); }; - bool forwardData(const map>& data) { + bool forwardData(const map>& data) { bool inserted = false; SAPFOR::BasicBlock* bb= getBlock(); @@ -298,7 +298,7 @@ public: const vector& getResult() { return useful; }; }; -class DeadCodeAnalysis : public BackwardDataFlowAnalysis>, DeadCodeAnalysisNode> { +class DeadCodeAnalysis : public BackwardDataFlowAnalysis>, DeadCodeAnalysisNode> { protected: vector& formal_parameters; -- 2.49.1 From de6e3bbd55960f0c1c7729ab7cc9120dc5287f00 Mon Sep 17 00:00:00 2001 From: mkoch Date: Wed, 10 Jan 2024 23:53:12 +0300 Subject: [PATCH 5/6] DATA_FLOW code style improvements: move template definitions to separate files, encapsulate CNT_NOTINIT constant --- sapfor/experts/Sapfor_2017/CMakeLists.txt | 2 + .../CFGraph/DataFlow/backward_data_flow.h | 90 +------------- .../DataFlow/backward_data_flow_impl.h | 103 ++++++++++++++++ .../_src/CFGraph/DataFlow/data_flow.h | 102 +--------------- .../_src/CFGraph/DataFlow/data_flow_impl.h | 113 ++++++++++++++++++ .../_src/CFGraph/live_variable_analysis.cpp | 2 +- 6 files changed, 224 insertions(+), 188 deletions(-) create mode 100644 sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow_impl.h create mode 100644 sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow_impl.h diff --git a/sapfor/experts/Sapfor_2017/CMakeLists.txt b/sapfor/experts/Sapfor_2017/CMakeLists.txt index 94433f2..be43305 100644 --- a/sapfor/experts/Sapfor_2017/CMakeLists.txt +++ b/sapfor/experts/Sapfor_2017/CMakeLists.txt @@ -223,7 +223,9 @@ set(CFG _src/CFGraph/IR.cpp set(DATA_FLOW _src/CFGraph/DataFlow/data_flow.h + _src/CFGraph/DataFlow/data_flow_impl.h _src/CFGraph/DataFlow/backward_data_flow.h + _src/CFGraph/DataFlow/backward_data_flow_impl.h ) set(CREATE_INTER_T _src/CreateInterTree/CreateInterTree.cpp 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 dd0b3c3..58009c9 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 @@ -8,7 +8,6 @@ #include "../../Utils/SgUtils.h" #include "../CFGraph.h" #include "../IR.h" -#include "../RD_subst.h" template class BackwardDataFlowAnalysis : public DataFlowAnalysis { @@ -18,91 +17,4 @@ public: void fit(const std::vector& blocks); }; -// minimizes the number of blocks beween the ends of back edges -template -std::vector BackwardDataFlowAnalysis::reorderSequence(const std::vector& blocks, - const std::set back_edge_sources) -{ - std::vector res = { }; - - auto blocks_end = blocks.rend(); - for (auto it = blocks.rbegin(); it < blocks_end; it++) - { - SAPFOR::BasicBlock* curr = *it; - auto res_end = res.end(); - auto inserter = res.begin(); - if (back_edge_sources.count(curr) == 0) - { - auto curr_next_begin = curr->getNext().begin(); - auto curr_next_end = curr->getNext().end(); - while (inserter < res_end && std::find(curr_next_begin, curr_next_end, *inserter) == curr_next_end) - inserter++; - } - - res.insert(inserter, curr); - } - - return res; -} - -template -void BackwardDataFlowAnalysis::fit(const std::vector& blocks) -{ - std::set> back_edges = {}; - - bool returned = false; - std::map> back_edges_by_src; - - auto blocks_sorted = sortCfgNodes(blocks, &back_edges); - - std::set back_edge_sources; - - for (auto& edge : back_edges) - { - back_edges_by_src[edge.first].insert(edge.second); - back_edge_sources.insert(edge.first); - } - - back_edges.clear(); - - blocks_sorted = reorderSequence(blocks_sorted, back_edge_sources); - back_edge_sources.clear(); - - std::reverse(blocks_sorted.begin(), blocks_sorted.end()); - - nodes.clear(); - std::map node_by_block; - - for (auto block : blocks_sorted) - { - NodeType* node = createNode(block); - nodes.push_back(node); - node_by_block[block] = node; - } - - int nodes_size = nodes.size(); - - for (int i = 0; i < nodes_size; i++) - { - NodeType* node = nodes[i]; - - auto back_edges_by_src_it = back_edges_by_src.find(node->getBlock()); - if (back_edges_by_src_it != back_edges_by_src.end()) - { - // This node is a source for back edge - for (auto dest : back_edges_by_src_it->second) - { - auto node_by_block_it = node_by_block.find(dest); - if (node_by_block_it != node_by_block.end()) - node_by_block_it->second->getRollback().insert(i); - } - } - - for (auto next : node->getBlock()->getNext()) - { - auto node_by_block_it = node_by_block.find(next); - if (node_by_block_it != node_by_block.end()) - node->getPrevBlocks().insert(node_by_block_it->second); - } - } -} \ No newline at end of file +#include "backward_data_flow_impl.h" \ No newline at end of file diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow_impl.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow_impl.h new file mode 100644 index 0000000..d1d4486 --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/backward_data_flow_impl.h @@ -0,0 +1,103 @@ +#pragma once +#include "backward_data_flow.h" + +#include +#include +#include + +#include "../../Utils/SgUtils.h" +#include "../CFGraph.h" +#include "../IR.h" +#include "../RD_subst.h" + +/* Note: this file should be included in backward_data_flow.h to provide template definitions */ + +// minimizes the number of blocks beween the ends of back edges +template +std::vector +BackwardDataFlowAnalysis::reorderSequence(const std::vector& blocks, + const std::set back_edge_sources) +{ + std::vector res = { }; + + auto blocks_end = blocks.rend(); + for (auto it = blocks.rbegin(); it < blocks_end; it++) + { + SAPFOR::BasicBlock* curr = *it; + auto res_end = res.end(); + auto inserter = res.begin(); + if (back_edge_sources.count(curr) == 0) + { + auto curr_next_begin = curr->getNext().begin(); + auto curr_next_end = curr->getNext().end(); + while (inserter < res_end && std::find(curr_next_begin, curr_next_end, *inserter) == curr_next_end) + inserter++; + } + + res.insert(inserter, curr); + } + + return res; +} + +template +void BackwardDataFlowAnalysis::fit(const std::vector& blocks) +{ + std::set> back_edges = {}; + + bool returned = false; + std::map> back_edges_by_src; + + auto blocks_sorted = sortCfgNodes(blocks, &back_edges); + + std::set back_edge_sources; + + for (auto& edge : back_edges) + { + back_edges_by_src[edge.first].insert(edge.second); + back_edge_sources.insert(edge.first); + } + + back_edges.clear(); + + blocks_sorted = reorderSequence(blocks_sorted, back_edge_sources); + back_edge_sources.clear(); + + std::reverse(blocks_sorted.begin(), blocks_sorted.end()); + + nodes.clear(); + std::map node_by_block; + + for (auto block : blocks_sorted) + { + NodeType* node = createNode(block); + nodes.push_back(node); + node_by_block[block] = node; + } + + int nodes_size = nodes.size(); + + for (int i = 0; i < nodes_size; i++) + { + NodeType* node = nodes[i]; + + auto back_edges_by_src_it = back_edges_by_src.find(node->getBlock()); + if (back_edges_by_src_it != back_edges_by_src.end()) + { + // This node is a source for back edge + for (auto dest : back_edges_by_src_it->second) + { + auto node_by_block_it = node_by_block.find(dest); + if (node_by_block_it != node_by_block.end()) + node_by_block_it->second->getRollback().insert(i); + } + } + + for (auto next : node->getBlock()->getNext()) + { + auto node_by_block_it = node_by_block.find(next); + if (node_by_block_it != node_by_block.end()) + node->getPrevBlocks().insert(node_by_block_it->second); + } + } +} \ No newline at end of file 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 d4ac744..11493a0 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h @@ -6,13 +6,10 @@ #include "../CFGraph.h" #include "../IR.h" -enum -{ - CNT_NOTINIT = 0 -}; - template class DataFlowAnalysisNode { + static const int CNT_NOTINIT = 0; + int in_cnt = CNT_NOTINIT, out_cnt = CNT_NOTINIT; std::set rollback; @@ -41,6 +38,7 @@ public: void setInCnt(int cnt) { in_cnt = cnt; } void setOutCnt(int cnt) { out_cnt = cnt; } + static int getStartCounter() { return CNT_NOTINIT; } std::set& getRollback() { return rollback; } std::set& getIgnoreRollback() { return ignore_rollback; } @@ -66,96 +64,4 @@ public: ~DataFlowAnalysis(); }; -template -DataFlowAnalysisNode::DataFlowAnalysisNode() { - getRollback() = {}; - getIgnoreRollback() = {}; - prev_blocks = {}; -} - -template -void DataFlowAnalysisNode::doStep() -{ - int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT; - for (auto next : prev_blocks) - { - if (in_cnt < next->out_cnt) - { - for (const auto& byOut : next->getOut()) - { - bool inserted = addIn({ byOut }); - - if (inserted) - { - if (next->out_cnt > in_max_cnt) - in_max_cnt = next->out_cnt; - - inserted = forwardData({ byOut }); - - if (inserted && next->out_cnt > out_max_cnt) - out_max_cnt = next->out_cnt; - } - } - } - } - - bool was_notinit = (out_cnt == CNT_NOTINIT); - - if (out_max_cnt != CNT_NOTINIT) - out_cnt = out_max_cnt; - - if (in_max_cnt != CNT_NOTINIT) - in_cnt = in_max_cnt; - - // TODO: fix counter overflow - if (was_notinit) - { - out_cnt++; - in_cnt++; - } -} - -template -void DataFlowAnalysis::analyze() { - auto curr = 0; - auto stop = nodes.size(); - - while (curr != stop) - { - auto curr_bb = nodes[curr]; - curr_bb->doStep(); - - const auto& jumps = curr_bb->getRollback(); - if (jumps.size() != 0) - { - auto& ignored_jumps = curr_bb->getIgnoreRollback(); - - bool jump = false; - for (const auto& jump_to : jumps) - { - if (ignored_jumps.insert(jump_to).second && curr_bb->newerThan(nodes[jump_to])) - { - jump = true; - curr = jump_to; - break; - } - } - - if (!jump) - curr_bb->getIgnoreRollback().clear(); - else - continue; - } - - curr++; - } -} - -template -DataFlowAnalysis::~DataFlowAnalysis() -{ - for (DataFlowAnalysisNode* node : nodes) - delete node; - - nodes.clear(); -} \ No newline at end of file +#include "data_flow_impl.h" \ No newline at end of file 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 new file mode 100644 index 0000000..da5a5fb --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow_impl.h @@ -0,0 +1,113 @@ +#pragma once +#include "data_flow.h" + +#include +#include + +#include "../../Utils/SgUtils.h" +#include "../CFGraph.h" +#include "../IR.h" + +/* Note: this file should be included in data_flow.h to provide template definitions */ + +/* definitions for DataFlowAnalysisNode class */ + +template +const int DataFlowAnalysisNode::CNT_NOTINIT; + +template +DataFlowAnalysisNode::DataFlowAnalysisNode() +{ + getRollback() = {}; + getIgnoreRollback() = {}; + prev_blocks = {}; +} + +template +void DataFlowAnalysisNode::doStep() +{ + int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT; + for (auto next : prev_blocks) + { + if (in_cnt < next->out_cnt) + { + for (const auto& byOut : next->getOut()) + { + bool inserted = addIn({ byOut }); + + if (inserted) + { + if (next->out_cnt > in_max_cnt) + in_max_cnt = next->out_cnt; + + inserted = forwardData({ byOut }); + + if (inserted && next->out_cnt > out_max_cnt) + out_max_cnt = next->out_cnt; + } + } + } + } + + bool was_notinit = (out_cnt == CNT_NOTINIT); + + if (out_max_cnt != CNT_NOTINIT) + out_cnt = out_max_cnt; + + if (in_max_cnt != CNT_NOTINIT) + in_cnt = in_max_cnt; + + // TODO: fix counter overflow + if (was_notinit) + { + out_cnt++; + in_cnt++; + } +} + +/* definitions for DataFlowAnalysis class */ + +template +void DataFlowAnalysis::analyze() { + auto curr = 0; + auto stop = nodes.size(); + + while (curr != stop) + { + auto curr_bb = nodes[curr]; + curr_bb->doStep(); + + const auto& jumps = curr_bb->getRollback(); + if (jumps.size() != 0) + { + auto& ignored_jumps = curr_bb->getIgnoreRollback(); + + bool jump = false; + for (const auto& jump_to : jumps) + { + if (ignored_jumps.insert(jump_to).second && curr_bb->newerThan(nodes[jump_to])) + { + jump = true; + curr = jump_to; + break; + } + } + + if (!jump) + curr_bb->getIgnoreRollback().clear(); + else + continue; + } + + curr++; + } +} + +template +DataFlowAnalysis::~DataFlowAnalysis() +{ + for (DataFlowAnalysisNode* node : nodes) + delete node; + + nodes.clear(); +} \ No newline at end of file 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 0836b52..0919566 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -684,7 +684,7 @@ void runLiveVariableAnalysis(const map>& } set exits; - int max_cnt = CNT_NOTINIT; + int max_cnt = LiveVarAnalysisNode::getStartCounter(); for (auto block : func_it->second->getNodes()) { if (block->getBlock()->getNext().size() == 0) -- 2.49.1 From dcb42889da1677c09f51bc519c70a1b5a0500573 Mon Sep 17 00:00:00 2001 From: mkoch Date: Fri, 12 Jan 2024 16:11:21 +0300 Subject: [PATCH 6/6] live variables analysis: rename fcall structure to LiveDeadVarsForCall class --- .../_src/CFGraph/live_variable_analysis.cpp | 34 +++++++++---------- .../_src/CFGraph/live_variable_analysis.h | 8 +++-- .../_src/Transformations/dead_code.cpp | 2 +- 3 files changed, 23 insertions(+), 21 deletions(-) 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 0919566..48bdff8 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.cpp @@ -17,7 +17,7 @@ using std::set; using std::unordered_map; using std::list; -using LIVE_VARIABLES::fcall; +using LIVE_VARIABLES::LiveDeadVarsForCall; namespace SAPFOR { @@ -152,7 +152,7 @@ namespace SAPFOR } } -bool fcall::tryInsert(set& dest, SAPFOR::BasicBlock* b) +bool LiveDeadVarsForCall::tryInsert(set& dest, SAPFOR::BasicBlock* b) { if (b == block || dest.find(block) == dest.end()) { @@ -163,7 +163,7 @@ bool fcall::tryInsert(set& dest, SAPFOR::BasicBlock* b) return false; } -fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector& p) +LiveDeadVarsForCall::LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector& p) { block = b; func = f; @@ -176,7 +176,7 @@ fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector params[i] = p[i]; } -void fcall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) +void LiveDeadVarsForCall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) { if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) { @@ -193,7 +193,7 @@ void fcall::make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b) } } -void fcall::make_dead(SAPFOR::Argument* arg) +void LiveDeadVarsForCall::make_dead(SAPFOR::Argument* arg) { if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_) { @@ -210,7 +210,7 @@ void fcall::make_dead(SAPFOR::Argument* arg) } } -void fcall::updateFromOut() +void LiveDeadVarsForCall::updateFromOut() { for (const auto& p : block->getLiveOut()) for (auto b : p.second) @@ -221,7 +221,7 @@ static bool getLiveDead(const vector& params, const string& f set& live, set& dead); static void buildUseDef(SAPFOR::BasicBlock* block, set& use, set& def, - vector& formal_parameters, vector& fcalls, + vector& formal_parameters, vector& fcalls, const map& funcByName, bool interprocedural); class LiveVarAnalysisNode : public DataFlowAnalysisNode>> { @@ -260,7 +260,7 @@ public: }; LiveVarAnalysisNode(SAPFOR::BasicBlock* block, vector& formal_parameters, - vector& fcalls, const map& funcByName) + vector& fcalls, const map& funcByName) { setBlock(block); @@ -274,21 +274,21 @@ public: class LiveVarAnalysis : public BackwardDataFlowAnalysis>, LiveVarAnalysisNode> { protected: vector& formal_parameters; - vector& fcalls; + vector& fcalls; const map& funcByName; LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override { return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName); }; public: - LiveVarAnalysis(vector& formal_parameters, vector& fcalls, + LiveVarAnalysis(vector& formal_parameters, vector& fcalls, const map& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName) { }; }; void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, set& use, set& def, - vector& formal_parameters, vector& fcalls, + vector& formal_parameters, vector& fcalls, vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, string& fName, const map& funcByName, bool interprocedural) { @@ -340,7 +340,7 @@ void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* ins auto func_it = funcByName.find(fName); if (func_it != funcByName.end()) { - fcalls.push_back(fcall(func_it->second, block, lastParamRef)); + fcalls.push_back(LiveDeadVarsForCall(func_it->second, block, lastParamRef)); auto r_it = fcalls.rbegin(); auto r_end = fcalls.rend(); @@ -376,7 +376,7 @@ void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* ins static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, set& use, set& def, - vector& formal_parameters, vector& fcalls, + vector& formal_parameters, vector& fcalls, vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, string& fName, const map& funcByName, bool interprocedural) { @@ -411,7 +411,7 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru //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& fcalls, + vector& formal_parameters, vector& fcalls, const map& funcByName, bool interprocedural) { vector lastParamRef; @@ -610,7 +610,7 @@ void runLiveVariableAnalysis(const map>& map func_to_analysis_object; map> func_to_parameters; - list> live_for_fcalls; + list> live_for_fcalls; //TODO: take into account ssc structure // main stage @@ -639,7 +639,7 @@ void runLiveVariableAnalysis(const map>& // interprocedural analysis for (auto& calls_vector : live_for_fcalls) { - map assembled_fcalls; + map assembled_fcalls; for (auto& call : calls_vector) { call.updateFromOut(); @@ -649,7 +649,7 @@ void runLiveVariableAnalysis(const map>& auto it = assembled_fcalls.find(call.func); if (it == assembled_fcalls.end()) - it = assembled_fcalls.insert({ call.func, fcall(call.func, call.block, {}) }).first; + it = assembled_fcalls.insert({ call.func, LiveDeadVarsForCall(call.func, call.block, {}) }).first; for (const auto& p : call.live_after) it->second.live_after[p.first].insert(p.second.begin(), p.second.end()); diff --git a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h index a697273..d4a2c6a 100644 --- a/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h +++ b/sapfor/experts/Sapfor_2017/_src/CFGraph/live_variable_analysis.h @@ -5,7 +5,9 @@ namespace LIVE_VARIABLES { - struct fcall + /* Store information about live and dead variables after call operator */ + /* (needed for interprocedural part of live variable analysis) */ + class LiveDeadVarsForCall { private: bool tryInsert(std::set& dest, SAPFOR::BasicBlock* b); @@ -21,7 +23,7 @@ namespace LIVE_VARIABLES std::vector params; SAPFOR::BasicBlock* block; - fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector& p); + LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector& p); void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b); void make_dead(SAPFOR::Argument* arg); @@ -39,7 +41,7 @@ void insertIfVar(IT begin, IT end, DEST& to) { void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr, std::set& use, std::set& def, - std::vector& formal_parameters, std::vector& fcalls, + std::vector& formal_parameters, std::vector& fcalls, std::vector& lastParamRef, int& last_param_ref_index, int& last_param_ref_size, std::string& fName, const std::map& funcByName, bool interprocedural); diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp index 9280ecd..f1ad920 100644 --- a/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp @@ -23,7 +23,7 @@ static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instru if (fName == "") last_fcall_useful = false; - vector fcalls; + vector fcalls; getUseDefForInstruction(block, instr, -- 2.49.1