3 Commits

Author SHA1 Message Date
Михаил Кочармин
c3827ed8f6 initial version of dead code analysis (dirty) 2024-01-06 17:26:19 +03:00
Михаил Кочармин
48998998d3 extract data flow analysis from live variables 2024-01-02 19:47:28 +03:00
Михаил Кочармин
168e190c7a improve def/use analysis 2024-01-01 18:08:56 +03:00
8 changed files with 615 additions and 389 deletions

View File

@@ -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}
@@ -217,7 +220,11 @@ set(CFG _src/CFGraph/IR.cpp
_src/CFGraph/private_variables_analysis.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 +384,7 @@ set(ZLIB ${zlib_sources}/src/adler32.c
set(SOURCE_EXE
${CFG}
${DATA_FLOW}
${CREATE_INTER_T}
${DIRA}
${DISTR}
@@ -406,8 +414,10 @@ 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\\DeadCodeRemoving FILES ${TR_DEAD_CODE})
source_group (Transformations\\CheckPoints FILES ${TR_CP})
source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP})
source_group (Transformations\\LoopNesting FILES ${TR_LOOP_NEST})

View File

@@ -33,6 +33,7 @@ namespace SAPFOR
bool addLive(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add, bool in);
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLive(bool in) const;
bool removeLive(SAPFOR::Argument* to_remove, bool in);
public:
BasicBlock() { num = lastNumBlock++; }
BasicBlock(IR_Block* item);
@@ -74,6 +75,10 @@ namespace SAPFOR
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
bool removeLiveIn(SAPFOR::Argument* to_remove) { return removeLive(to_remove, true); };
bool removeLiveOut(SAPFOR::Argument* to_remove) { return removeLive(to_remove, false); };
void compressLives();
/*

View File

@@ -0,0 +1,108 @@
#pragma once
#include "data_flow.h"
#include <vector>
#include <set>
#include <algorithm>
#include "../../Utils/SgUtils.h"
#include "../CFGraph.h"
#include "../IR.h"
#include "../RD_subst.h"
template <class DataType, class NodeType>
class BackwardDataFlowAnalysis : public DataFlowAnalysis<DataType, NodeType> {
std::vector<SAPFOR::BasicBlock*> reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
const std::set<SAPFOR::BasicBlock*> back_edge_sources);
public:
void fit(const std::vector<SAPFOR::BasicBlock*>& blocks);
};
// minimizes the number of blocks beween the ends of back edges
template <class DataType, class NodeType>
std::vector<SAPFOR::BasicBlock*> BackwardDataFlowAnalysis<DataType, NodeType>::reorderSequence(const std::vector<SAPFOR::BasicBlock*>& blocks,
const std::set<SAPFOR::BasicBlock*> back_edge_sources)
{
std::vector<SAPFOR::BasicBlock*> 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 <class DataType, class NodeType>
void BackwardDataFlowAnalysis<DataType, NodeType>::fit(const std::vector<SAPFOR::BasicBlock*>& blocks)
{
std::set<std::pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> back_edges = {};
bool returned = false;
std::map<SAPFOR::BasicBlock*, std::set<SAPFOR::BasicBlock*>> back_edges_by_src;
auto blocks_sorted = sortCfgNodes(blocks, &back_edges);
std::set<SAPFOR::BasicBlock*> 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<SAPFOR::BasicBlock*, NodeType*> 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);
}
}
}

View File

@@ -0,0 +1,161 @@
#pragma once
#include<vector>
#include<set>
#include "../../Utils/SgUtils.h"
#include "../CFGraph.h"
#include "../IR.h"
enum
{
CNT_NOTINIT = 0
};
template <class DataType>
class DataFlowAnalysisNode {
int in_cnt = CNT_NOTINIT, out_cnt = CNT_NOTINIT;
std::set<int> rollback;
std::set<int> ignore_rollback;
std::set<DataFlowAnalysisNode<DataType>*> 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<DataType>* 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<int>& getRollback() { return rollback; }
std::set<int>& getIgnoreRollback() { return ignore_rollback; }
std::set<DataFlowAnalysisNode<DataType>*>& getPrevBlocks() { return prev_blocks; }
SAPFOR::BasicBlock* getBlock() { return bb; }
void setBlock(SAPFOR::BasicBlock* b) { bb = b; }
};
template <class DataType, class NodeType>
class DataFlowAnalysis {
protected:
std::vector<NodeType*> nodes;
virtual NodeType* createNode(SAPFOR::BasicBlock* block) = 0;
public:
virtual void fit(const std::vector<SAPFOR::BasicBlock*>& blocks) = 0;
void analyze();
const std::vector<NodeType*>& getNodes() { return nodes; }
~DataFlowAnalysis();
};
template <class DataType>
DataFlowAnalysisNode<DataType>::DataFlowAnalysisNode() {
getRollback() = {};
getIgnoreRollback() = {};
prev_blocks = {};
}
template <class DataType>
void DataFlowAnalysisNode<DataType>::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 <class DataType, class NodeType>
void DataFlowAnalysis<DataType, NodeType>::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 <class DataType, class NodeType>
DataFlowAnalysis<DataType, NodeType>::~DataFlowAnalysis()
{
for (DataFlowAnalysisNode<DataType>* node : nodes)
delete node;
nodes.clear();
}

View File

@@ -1,4 +1,5 @@
#include "live_variable_analysis.h"
#include "DataFlow/backward_data_flow.h"
#include "RD_subst.h"
#include <string>
@@ -16,6 +17,8 @@ using std::set;
using std::unordered_map;
using std::list;
using LIVE_VARIABLES::fcall;
namespace SAPFOR
{
bool BasicBlock::addLive(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& to_add, bool in) {
@@ -27,7 +30,7 @@ namespace SAPFOR
{
const set<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
set<SAPFOR::BasicBlock*> new_in_live = {};
auto current_set_iter = current_set.find(byNew.first);
if (current_set_iter == current_set.end())
@@ -105,411 +108,317 @@ namespace SAPFOR
return res;
}
void BasicBlock::compressLives() {
for (auto& bySrc : { &live_in, &live_out, &live_inout })
for (auto& byArg : *bySrc)
byArg.second.shrink_to_fit();
}
bool BasicBlock::removeLive(SAPFOR::Argument* to_remove, bool in) {
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& current_set = (in ? live_in : live_out);
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& 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;
};
}
struct fcall
bool fcall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
{
private:
bool tryInsert(set<SAPFOR::BasicBlock*>& 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<int, set<SAPFOR::BasicBlock*>> live_after;
set<int> dead_after;
return false;
}
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> commons_live_after;
set<SAPFOR::Argument*> commons_dead_after;
fcall::fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
{
block = b;
func = f;
vector<SAPFOR::Argument*> params;
SAPFOR::BasicBlock* block;
int param_size = p.size();
params = vector<SAPFOR::Argument*>(param_size, NULL);
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
{
block = b;
func = f;
int param_size = p.size();
params = vector<SAPFOR::Argument*>(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<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead);
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName);
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural);
enum
{
CNT_NOTINIT = 0
};
struct BasicBlockNode
{
SAPFOR::BasicBlock* bb;
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> {
private:
set<SAPFOR::Argument*> live, dead;
int in_cnt, out_cnt;
set<BasicBlockNode*> next_blocks;
public:
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> getIn() {
return getBlock()->getLiveOut();
};
set<vector<BasicBlockNode*>::reverse_iterator> rollback;
set<vector<BasicBlockNode*>::reverse_iterator> ignore_rollback;
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> getOut() {
return getBlock()->getLiveIn();
};
BasicBlockNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
bool addIn(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& data) {
return getBlock()->addLiveOut(data);
};
bool addOut(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& data) {
return getBlock()->addLiveIn(data);
};
bool forwardData(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& 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<SAPFOR::Argument*>& formal_parameters,
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
{
bb = block;
out_cnt = in_cnt = CNT_NOTINIT;
setBlock(block);
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
buildUseDef(bb, live, dead, formal_parameters, fcalls, funcByName);
for (SAPFOR::Argument* arg : live)
bb->addLiveIn({ { arg, { bb } } });
rollback = {};
ignore_rollback = {};
next_blocks = {};
getBlock()->addLiveIn({ { arg, { getBlock() } } });
}
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; }
};
class LiveVarAnalysis : public BackwardDataFlowAnalysis<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>, LiveVarAnalysisNode> {
protected:
vector<SAPFOR::Argument*>& formal_parameters;
vector<fcall>& fcalls;
const map<string, FuncInfo*>& funcByName;
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
};
public:
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
{ };
};
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
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;
SAPFOR::Argument* res_arg = NULL;
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (hasStoreStructure(instr_operation))
{
res_arg = instr->getArg1();
set<SAPFOR::Argument*> 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();
last_param_ref_size = stoi(instr->getArg2()->getValue());
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<SAPFOR::Argument*> 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())
{
fcalls.push_back(fcall(func_it->second, block, lastParamRef));
auto r_it = fcalls.rbegin();
auto r_end = fcalls.rend();
for (auto e : def)
r_it->make_dead(e);
for (auto e : use)
r_it->make_live(e, block);
}
set<SAPFOR::Argument*> 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<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
set<SAPFOR::Argument*> 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);
}
}
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<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName)
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
const map<string, FuncInfo*>& funcByName, bool interprocedural)
{
set<SAPFOR::Argument*> tmp_use, tmp_def;
vector<SAPFOR::Argument*> lastParamRef;
bool fcall_added;
int last_param_ref_index = 0, last_param_ref_size = 0;
string fName;
for (auto ir_block : block->getInstructions())
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++)
{
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;
set<SAPFOR::Argument*> res = {}, args = {};
SAPFOR::Argument* res_arg = NULL;
static const set<SAPFOR::CFG_OP> skip = { SAPFOR::CFG_OP::ENTRY };
SAPFOR::CFG_OP instr_operation = instr->getOperation();
if (hasStoreStructure(instr_operation)) {
res_arg = instr->getArg1();
std::set<SAPFOR::Argument*> 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)
{
res_arg = instr->getResult();
int count = stoi(instr->getArg2()->getValue());
if (lastParamRef.size() != count)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
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<SAPFOR::Argument*> 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<SAPFOR::Argument*> 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)
r_it->make_dead(e);
r_it++;
}
updateUseDefForInstruction(block, (*ir_block_it)->getInstruction(),
use, def,
formal_parameters, fcalls,
lastParamRef, last_param_ref_index, last_param_ref_size,
fName, funcByName,
interprocedural
);
}
use = tmp_use;
def = tmp_def;
}
// minimizes the number of blocks beween the ends of back edges
static vector<SAPFOR::BasicBlock*> reorderSequence(const vector<SAPFOR::BasicBlock*>& blocks,
const set<SAPFOR::BasicBlock*> back_edge_sources)
{
vector<SAPFOR::BasicBlock*> 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<BasicBlockNode*> toBlocksWithCnt(const vector<SAPFOR::BasicBlock*>& blocks,
vector<SAPFOR::Argument*>& formal_parameters,
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
{
set<pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> back_edges = {};
bool returned = false;
map<SAPFOR::BasicBlock*, set<SAPFOR::BasicBlock*>> back_edges_by_src;
auto blocks_sorted = sortCfgNodes(blocks, &back_edges);
set<SAPFOR::BasicBlock*> 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<BasicBlockNode*> blocks_with_counters;
map<SAPFOR::BasicBlock*, BasicBlockNode*> 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<BasicBlockNode*>& 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<BasicBlockNode*>& blocks_with_counters)
{
for (auto to_free : blocks_with_counters)
delete to_free;
}
// prints info about live variables
@@ -527,7 +436,7 @@ void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& 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");
}
@@ -630,8 +539,8 @@ static void fillLiveDeadArgs(const FuncInfo* func, const vector<SAPFOR::BasicBlo
// unite global arguments and actual parameters with given indexes for function
// stores the result in the last argument
bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
const string& func_name, set<SAPFOR::Argument*>& result)
const map<string, pair<set<int>, set<SAPFOR::Argument*>>>& params_and_globals,
const string& func_name, set<SAPFOR::Argument*>& result)
{
auto globals_it = params_and_globals.find(func_name);
@@ -646,7 +555,7 @@ bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& 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
@@ -658,11 +567,11 @@ bool joinGlobalsWithParameters(const vector<SAPFOR::Argument*>& params,
}
// fill sets of arguments wich becomes live or dead after call with parameters params
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& dead)
static bool getLiveDead(const vector<SAPFOR::Argument*>& params, const string& func_name,
set<SAPFOR::Argument*>& live, set<SAPFOR::Argument*>& 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
@@ -682,11 +591,11 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
callDeps[byFunc.first].insert(byFunc.first->callsFromV.begin(), byFunc.first->callsFromV.end());
funcByName[byFunc.first->funcName] = byFunc.first;
}
vector<set<FuncInfo*>> scc;
vector<set<FuncInfo*>> callLvls = groupByCallDependencies(callDeps, scc);
map<string, vector<BasicBlockNode*>> func_to_blocks_with_cnt;
map<string, LiveVarAnalysis*> func_to_analysis_object;
map<string, vector<SAPFOR::Argument*>> func_to_parameters;
list<vector<fcall>> live_for_fcalls;
@@ -707,8 +616,9 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
auto& params = func_to_parameters[byFunc->funcName] = vector<SAPFOR::Argument*>(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 +638,7 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
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 +648,12 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
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<SAPFOR::Argument*>& params = param_it->second;
@@ -761,14 +671,14 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
}
}
set<BasicBlockNode*> exits;
set<LiveVarAnalysisNode*> 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 +687,22 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
{
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)

View File

@@ -1,6 +1,33 @@
#include "../Utils/SgUtils.h"
#include "CFGraph.h"
namespace LIVE_VARIABLES
{
struct fcall
{
private:
bool tryInsert(std::set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b);
public:
FuncInfo* func;
std::map<int, std::set<SAPFOR::BasicBlock*>> live_after;
std::set<int> dead_after;
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> commons_live_after;
std::set<SAPFOR::Argument*> commons_dead_after;
std::vector<SAPFOR::Argument*> params;
SAPFOR::BasicBlock* block;
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const std::vector<SAPFOR::Argument*>& p);
void make_live(SAPFOR::Argument* arg, SAPFOR::BasicBlock* b);
void make_dead(SAPFOR::Argument* arg);
void updateFromOut();
};
}
template <class IT, class DEST>
void insertIfVar(IT begin, IT end, DEST& to) {
for (auto it = begin; it != end; it++)
@@ -8,6 +35,12 @@ void insertIfVar(IT begin, IT end, DEST& to) {
to.insert(*it);
};
void getUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
std::set<SAPFOR::Argument*>& use, std::set<SAPFOR::Argument*>& def,
std::vector<SAPFOR::Argument*>& formal_parameters, std::vector<LIVE_VARIABLES::fcall>& fcalls,
std::vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
std::string& fName, const std::map<std::string, FuncInfo*>& funcByName, bool interprocedural);
void runLiveVariableAnalysis(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);
void doDumpLive(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*>>& CFGraph_for_project);