From 5f8940f34d032a593ed913be4cbcc9e1cd7ec354 Mon Sep 17 00:00:00 2001 From: mkoch Date: Tue, 9 Jan 2024 18:13:56 +0300 Subject: [PATCH] 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);