dead_code_removing (Новый проход) #21
@@ -161,6 +161,8 @@ set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp
|
||||
_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}
|
||||
@@ -218,6 +221,13 @@ set(CFG _src/CFGraph/IR.cpp
|
||||
_src/CFGraph/private_variables_analysis.h
|
||||
)
|
||||
|
||||
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
|
||||
_src/CreateInterTree/CreateInterTree.h)
|
||||
|
||||
@@ -377,6 +387,7 @@ set(ZLIB ${zlib_sources}/src/adler32.c
|
||||
|
||||
set(SOURCE_EXE
|
||||
${CFG}
|
||||
${DATA_FLOW}
|
||||
${CREATE_INTER_T}
|
||||
${DIRA}
|
||||
${DISTR}
|
||||
@@ -406,7 +417,9 @@ set(SOURCE_EXE
|
||||
|
||||
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})
|
||||
|
||||
@@ -31,8 +31,9 @@ namespace SAPFOR
|
||||
//live variables [arg -> blocks with usages]
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> live_in, live_out, live_inout;
|
||||
|
||||
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 addLive(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add, bool in);
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLive(bool in) const;
|
||||
bool removeLive(SAPFOR::Argument* to_remove, bool in);
|
||||
public:
|
||||
BasicBlock() { num = lastNumBlock++; }
|
||||
BasicBlock(IR_Block* item);
|
||||
@@ -69,11 +70,14 @@ namespace SAPFOR
|
||||
/*
|
||||
* FOR LIVE ANALYSIS
|
||||
*/
|
||||
bool addLiveIn(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, true); };
|
||||
bool addLiveOut(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, false); };
|
||||
bool addLiveIn(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, true); };
|
||||
bool addLiveOut(const std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, false); };
|
||||
|
||||
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); };
|
||||
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
|
||||
std::map<SAPFOR::Argument*, std::vector<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
|
||||
void compressLives();
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "data_flow.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../../Utils/SgUtils.h"
|
||||
#include "../CFGraph.h"
|
||||
#include "../IR.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);
|
||||
};
|
||||
|
||||
#include "backward_data_flow_impl.h"
|
||||
@@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
#include "backward_data_flow.h"
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
#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 <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);
|
||||
}
|
||||
}
|
||||
}
|
||||
67
sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h
Normal file
67
sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
#include<vector>
|
||||
#include<set>
|
||||
|
||||
#include "../../Utils/SgUtils.h"
|
||||
#include "../CFGraph.h"
|
||||
#include "../IR.h"
|
||||
|
||||
template <class DataType>
|
||||
class DataFlowAnalysisNode {
|
||||
static const int CNT_NOTINIT = 0;
|
||||
|
||||
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; }
|
||||
static int getStartCounter() { return CNT_NOTINIT; }
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
#include "data_flow_impl.h"
|
||||
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
#include "data_flow.h"
|
||||
|
||||
#include<vector>
|
||||
#include<set>
|
||||
|
||||
#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 <class DataType>
|
||||
const int DataFlowAnalysisNode<DataType>::CNT_NOTINIT;
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
/* definitions for DataFlowAnalysis class */
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "live_variable_analysis.h"
|
||||
#include "RD_subst.h"
|
||||
#include "DataFlow/backward_data_flow.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -16,17 +17,19 @@ using std::set;
|
||||
using std::unordered_map;
|
||||
using std::list;
|
||||
|
||||
using LIVE_VARIABLES::LiveDeadVarsForCall;
|
||||
|
||||
namespace SAPFOR
|
||||
{
|
||||
bool BasicBlock::addLive(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& to_add, bool in) {
|
||||
bool BasicBlock::addLive(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& to_add, 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 inserted = false;
|
||||
for (const auto& byNew : to_add)
|
||||
{
|
||||
const set<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
|
||||
set<SAPFOR::BasicBlock*> new_in_live = {};
|
||||
const vector<SAPFOR::BasicBlock*>& add_in_live = byNew.second;
|
||||
vector<SAPFOR::BasicBlock*> new_in_live = {};
|
||||
|
||||
auto current_set_iter = current_set.find(byNew.first);
|
||||
|
||||
@@ -94,14 +97,50 @@ namespace SAPFOR
|
||||
return inserted;
|
||||
};
|
||||
|
||||
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
|
||||
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;
|
||||
};
|
||||
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
|
||||
auto& current_set = in ? live_in : live_out;
|
||||
|
||||
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> res;
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> 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;
|
||||
}
|
||||
@@ -113,10 +152,7 @@ namespace SAPFOR
|
||||
}
|
||||
}
|
||||
|
||||
struct fcall
|
||||
{
|
||||
private:
|
||||
bool tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
||||
bool LiveDeadVarsForCall::tryInsert(set<SAPFOR::BasicBlock*>& dest, SAPFOR::BasicBlock* b)
|
||||
{
|
||||
if (b == block || dest.find(block) == dest.end())
|
||||
{
|
||||
@@ -127,19 +163,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
FuncInfo* func;
|
||||
|
||||
map<int, set<SAPFOR::BasicBlock*>> live_after;
|
||||
set<int> dead_after;
|
||||
|
||||
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> commons_live_after;
|
||||
set<SAPFOR::Argument*> commons_dead_after;
|
||||
|
||||
vector<SAPFOR::Argument*> params;
|
||||
SAPFOR::BasicBlock* block;
|
||||
|
||||
fcall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
|
||||
LiveDeadVarsForCall::LiveDeadVarsForCall(FuncInfo* f, SAPFOR::BasicBlock* b, const vector<SAPFOR::Argument*>& p)
|
||||
{
|
||||
block = b;
|
||||
func = f;
|
||||
@@ -152,7 +176,7 @@ public:
|
||||
params[i] = p[i];
|
||||
}
|
||||
|
||||
void 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_)
|
||||
{
|
||||
@@ -169,347 +193,244 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void 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_)
|
||||
{
|
||||
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();
|
||||
if (live_after.find(idx) == live_after.end())
|
||||
dead_after.insert(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void updateFromOut()
|
||||
void LiveDeadVarsForCall::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<LiveDeadVarsForCall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName, bool interprocedural);
|
||||
|
||||
enum
|
||||
{
|
||||
CNT_NOTINIT = 0
|
||||
};
|
||||
|
||||
struct BasicBlockNode
|
||||
{
|
||||
SAPFOR::BasicBlock* bb;
|
||||
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
|
||||
private:
|
||||
set<SAPFOR::Argument*> live, dead;
|
||||
int in_cnt, out_cnt;
|
||||
set<BasicBlockNode*> next_blocks;
|
||||
|
||||
set<vector<BasicBlockNode*>::reverse_iterator> rollback;
|
||||
set<vector<BasicBlockNode*>::reverse_iterator> ignore_rollback;
|
||||
|
||||
BasicBlockNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
|
||||
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
||||
public:
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
|
||||
{
|
||||
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 getBlock()->getLiveOut();
|
||||
};
|
||||
|
||||
//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)
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
|
||||
{
|
||||
set<SAPFOR::Argument*> tmp_use, tmp_def;
|
||||
return getBlock()->getLiveIn();
|
||||
};
|
||||
|
||||
vector<SAPFOR::Argument*> lastParamRef;
|
||||
bool fcall_added;
|
||||
|
||||
for (auto ir_block : block->getInstructions())
|
||||
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
return getBlock()->addLiveOut(data);
|
||||
};
|
||||
|
||||
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
return getBlock()->addLiveIn(data);
|
||||
};
|
||||
|
||||
bool forwardData(const map<SAPFOR::Argument*, vector<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<LiveDeadVarsForCall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
||||
{
|
||||
setBlock(block);
|
||||
|
||||
buildUseDef(getBlock(), live, dead, formal_parameters, fcalls, funcByName, true);
|
||||
|
||||
for (SAPFOR::Argument* arg : live)
|
||||
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
||||
}
|
||||
};
|
||||
|
||||
class LiveVarAnalysis : public BackwardDataFlowAnalysis<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>, LiveVarAnalysisNode> {
|
||||
protected:
|
||||
vector<SAPFOR::Argument*>& formal_parameters;
|
||||
vector<LiveDeadVarsForCall>& 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<LiveDeadVarsForCall>& 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<LiveDeadVarsForCall>& fcalls,
|
||||
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
|
||||
string& fName, const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
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)) {
|
||||
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);
|
||||
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.push_back(instr->getArg1());
|
||||
{
|
||||
lastParamRef[last_param_ref_index--] = 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);
|
||||
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() };
|
||||
insertIfVar(intr_args.begin(), intr_args.end(), args);
|
||||
use.insert(intr_args.begin(), intr_args.end());
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
//skip
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
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(LiveDeadVarsForCall(func_it->second, block, lastParamRef));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
use = tmp_use;
|
||||
def = tmp_def;
|
||||
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());
|
||||
}
|
||||
|
||||
// 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;
|
||||
use.insert(lastParamRef.begin(), lastParamRef.end());
|
||||
|
||||
last_param_ref_index = 0;
|
||||
last_param_ref_size = 0;
|
||||
|
||||
lastParamRef.clear();
|
||||
fName = "";
|
||||
}
|
||||
|
||||
curr++;
|
||||
}
|
||||
if (res_arg)
|
||||
def.insert(res_arg);
|
||||
}
|
||||
|
||||
// delete all nodes from vector
|
||||
static void freeBlocksWithCnt(const vector<BasicBlockNode*>& blocks_with_counters)
|
||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<LiveDeadVarsForCall>& 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 to_free : blocks_with_counters)
|
||||
delete to_free;
|
||||
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<LiveDeadVarsForCall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName, bool interprocedural)
|
||||
{
|
||||
vector<SAPFOR::Argument*> 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
|
||||
@@ -686,10 +607,10 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
||||
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;
|
||||
list<vector<LiveDeadVarsForCall>> live_for_fcalls;
|
||||
|
||||
//TODO: take into account ssc structure
|
||||
// main stage
|
||||
@@ -707,8 +628,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);
|
||||
}
|
||||
@@ -717,7 +639,7 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
||||
// interprocedural analysis
|
||||
for (auto& calls_vector : live_for_fcalls)
|
||||
{
|
||||
map<FuncInfo*, fcall> assembled_fcalls;
|
||||
map<FuncInfo*, LiveDeadVarsForCall> assembled_fcalls;
|
||||
for (auto& call : calls_vector)
|
||||
{
|
||||
call.updateFromOut();
|
||||
@@ -727,7 +649,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;
|
||||
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());
|
||||
@@ -738,8 +660,8 @@ 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);
|
||||
@@ -761,14 +683,14 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
||||
}
|
||||
}
|
||||
|
||||
set<BasicBlockNode*> exits;
|
||||
int max_cnt = CNT_NOTINIT;
|
||||
for (auto block : func_it->second)
|
||||
set<LiveVarAnalysisNode*> exits;
|
||||
int max_cnt = LiveVarAnalysisNode::getStartCounter();
|
||||
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 +699,25 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
||||
{
|
||||
for (const auto& byArg : live_after)
|
||||
{
|
||||
if (exit->bb->addLiveOut({ byArg }))
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> converted;
|
||||
converted[byArg.first] = vector<SAPFOR::BasicBlock*>(byArg.second.begin(), byArg.second.end());
|
||||
|
||||
if (exit->addIn(converted))
|
||||
{
|
||||
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(converted))
|
||||
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)
|
||||
|
||||
@@ -1,6 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "CFGraph.h"
|
||||
|
||||
namespace LIVE_VARIABLES
|
||||
{
|
||||
/* 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<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;
|
||||
|
||||
LiveDeadVarsForCall(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 +39,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::LiveDeadVarsForCall>& 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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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";
|
||||
|
||||
436
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp
Normal file
436
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.cpp
Normal file
@@ -0,0 +1,436 @@
|
||||
#include "dead_code.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
using std::map;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
|
||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters,
|
||||
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
|
||||
string& fName,
|
||||
bool& useful, bool& last_fcall_useful,
|
||||
set<SAPFOR::Argument*>& usedByThisBlock)
|
||||
{
|
||||
set<SAPFOR::Argument*> res, args;
|
||||
|
||||
if (fName == "")
|
||||
last_fcall_useful = false;
|
||||
|
||||
vector<LIVE_VARIABLES::LiveDeadVarsForCall> 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<SAPFOR::CFG_OP> 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<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<bool>& useful,
|
||||
set<SAPFOR::Argument*>& usedByThisBlock)
|
||||
{
|
||||
set<SAPFOR::Argument*> use_with_regs = use, def_with_regs = def;
|
||||
|
||||
vector<SAPFOR::Argument*> 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<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>> {
|
||||
private:
|
||||
vector<bool> useful;
|
||||
bool useful_block = false;
|
||||
set<DeadCodeAnalysisNode*> next_notempty_in, next_notempty_out;
|
||||
bool useful_jump = false;
|
||||
|
||||
vector<SAPFOR::Argument*>& 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<DeadCodeAnalysisNode*>(*prev.begin())->next_notempty_out;
|
||||
|
||||
for (auto p : prev)
|
||||
{
|
||||
DeadCodeAnalysisNode* next = dynamic_cast<DeadCodeAnalysisNode*>(p);
|
||||
|
||||
if (next->next_notempty_out != example)
|
||||
{
|
||||
useful.back() = true;
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool updateNextNotEmpty()
|
||||
{
|
||||
bool updated = false;
|
||||
|
||||
if(!useful_block)
|
||||
{
|
||||
set<DeadCodeAnalysisNode*> current = {};
|
||||
|
||||
for (auto nextP : getPrevBlocks())
|
||||
{
|
||||
DeadCodeAnalysisNode* next = dynamic_cast<DeadCodeAnalysisNode*>(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<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn() {
|
||||
return getBlock()->getLiveOut();
|
||||
};
|
||||
|
||||
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut() {
|
||||
return getBlock()->getLiveIn();
|
||||
};
|
||||
|
||||
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data) {
|
||||
bool inserted = getBlock()->addLiveOut(data);
|
||||
|
||||
if (!useful_block)
|
||||
inserted |= updateNextNotEmpty();
|
||||
|
||||
inserted |= updateJumpStatus();
|
||||
|
||||
return inserted;
|
||||
};
|
||||
|
||||
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data) {
|
||||
return getBlock()->addLiveIn(data);
|
||||
};
|
||||
|
||||
bool forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data) {
|
||||
bool inserted = false;
|
||||
SAPFOR::BasicBlock* bb= getBlock();
|
||||
|
||||
set<SAPFOR::Argument*> use, def;
|
||||
|
||||
for (const auto& byArg : data)
|
||||
use.insert(byArg.first);
|
||||
|
||||
set<SAPFOR::Argument*> 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<SAPFOR::Argument*>& formal_parameters) :
|
||||
formal_parameters(formal_parameters)
|
||||
{
|
||||
setBlock(block);
|
||||
useful.resize(block->getInstructions().size(), false);
|
||||
set<SAPFOR::Argument*> use, def;
|
||||
set<SAPFOR::Argument*> usedByThisBlock;
|
||||
|
||||
buildUseDef(getBlock(), use, def, this->formal_parameters, useful, usedByThisBlock);
|
||||
|
||||
for (SAPFOR::Argument* arg : use)
|
||||
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
||||
}
|
||||
|
||||
const vector<bool>& getResult() { return useful; };
|
||||
};
|
||||
|
||||
class DeadCodeAnalysis : public BackwardDataFlowAnalysis<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>, DeadCodeAnalysisNode> {
|
||||
protected:
|
||||
vector<SAPFOR::Argument*>& formal_parameters;
|
||||
|
||||
DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
|
||||
return new DeadCodeAnalysisNode(block, formal_parameters);
|
||||
};
|
||||
public:
|
||||
DeadCodeAnalysis(vector<SAPFOR::Argument*>& formal_parameters) :
|
||||
formal_parameters(formal_parameters)
|
||||
{ };
|
||||
};
|
||||
|
||||
|
||||
void removeDeadCode(SgStatement* func,
|
||||
const map<string, vector<FuncInfo*>>& allFuncs,
|
||||
const map<string, CommonBlock*>& 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<SAPFOR::Argument*> 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<SgStatement*> 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<int> 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;
|
||||
}
|
||||
}
|
||||
14
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h
Normal file
14
sapfor/experts/Sapfor_2017/_src/Transformations/dead_code.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include<string>
|
||||
#include<vector>
|
||||
|
||||
#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<std::string, std::vector<FuncInfo*>>&allFuncs,
|
||||
const std::map<std::string, CommonBlock*>& commonBlocks);
|
||||
@@ -306,6 +306,8 @@ void InitPassesDependencies(map<passes, vector<passes>> &passDepsIn, set<passes>
|
||||
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user