extract data flow analysis from live variables
This commit is contained in:
@@ -217,7 +217,11 @@ set(CFG _src/CFGraph/IR.cpp
|
|||||||
_src/CFGraph/private_variables_analysis.cpp
|
_src/CFGraph/private_variables_analysis.cpp
|
||||||
_src/CFGraph/private_variables_analysis.h
|
_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
|
set(CREATE_INTER_T _src/CreateInterTree/CreateInterTree.cpp
|
||||||
_src/CreateInterTree/CreateInterTree.h)
|
_src/CreateInterTree/CreateInterTree.h)
|
||||||
|
|
||||||
@@ -377,6 +381,7 @@ set(ZLIB ${zlib_sources}/src/adler32.c
|
|||||||
|
|
||||||
set(SOURCE_EXE
|
set(SOURCE_EXE
|
||||||
${CFG}
|
${CFG}
|
||||||
|
${DATA_FLOW}
|
||||||
${CREATE_INTER_T}
|
${CREATE_INTER_T}
|
||||||
${DIRA}
|
${DIRA}
|
||||||
${DISTR}
|
${DISTR}
|
||||||
@@ -406,6 +411,7 @@ set(SOURCE_EXE
|
|||||||
|
|
||||||
add_executable(Sapfor_F ${SOURCE_EXE})
|
add_executable(Sapfor_F ${SOURCE_EXE})
|
||||||
source_group (CFGraph FILES ${CFG})
|
source_group (CFGraph FILES ${CFG})
|
||||||
|
source_group (CFGraph\\DataFlow FILES ${DATA_FLOW})
|
||||||
|
|
||||||
source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM})
|
source_group (Transformations\\ExpressionSubstitution FILES ${EXPR_TRANSFORM})
|
||||||
source_group (Transformations\\CheckPoints FILES ${TR_CP})
|
source_group (Transformations\\CheckPoints FILES ${TR_CP})
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
161
sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h
Normal file
161
sapfor/experts/Sapfor_2017/_src/CFGraph/DataFlow/data_flow.h
Normal 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();
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "live_variable_analysis.h"
|
#include "live_variable_analysis.h"
|
||||||
|
#include "DataFlow/forward_data_flow.h"
|
||||||
#include "RD_subst.h"
|
#include "RD_subst.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -205,52 +206,66 @@ static void buildUseDef2(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use,
|
|||||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||||
const map<string, FuncInfo*>& funcByName);
|
const map<string, FuncInfo*>& funcByName);
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
CNT_NOTINIT = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BasicBlockNode
|
class LiveVarAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>> {
|
||||||
{
|
private:
|
||||||
SAPFOR::BasicBlock* bb;
|
|
||||||
set<SAPFOR::Argument*> live, dead;
|
set<SAPFOR::Argument*> live, dead;
|
||||||
int in_cnt, out_cnt;
|
public:
|
||||||
set<BasicBlockNode*> next_blocks;
|
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> getIn() {
|
||||||
|
return getBlock()->getLiveOut();
|
||||||
|
};
|
||||||
|
|
||||||
set<vector<BasicBlockNode*>::reverse_iterator> rollback;
|
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> getOut() {
|
||||||
set<vector<BasicBlockNode*>::reverse_iterator> ignore_rollback;
|
return getBlock()->getLiveIn();
|
||||||
|
};
|
||||||
|
|
||||||
BasicBlockNode(SAPFOR::BasicBlock* block, vector<SAPFOR::Argument*>& formal_parameters,
|
bool addIn(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& data) {
|
||||||
vector<fcall>& fcalls, const map<string, FuncInfo*>& funcByName)
|
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;
|
setBlock(block);
|
||||||
out_cnt = in_cnt = CNT_NOTINIT;
|
|
||||||
|
|
||||||
set<SAPFOR::Argument*> live1, dead1;
|
set<SAPFOR::Argument*> live1, dead1;
|
||||||
vector<SAPFOR::Argument*> formal_parameters1 = formal_parameters;
|
vector<SAPFOR::Argument*> formal_parameters1 = formal_parameters;
|
||||||
vector<fcall> fcalls1;
|
vector<fcall> fcalls1;
|
||||||
|
|
||||||
buildUseDef(bb, live1, dead1, formal_parameters1, fcalls1, funcByName);
|
buildUseDef(getBlock(), live1, dead1, formal_parameters1, fcalls1, funcByName);
|
||||||
|
|
||||||
|
|
||||||
set<SAPFOR::Argument*> live2, dead2;
|
set<SAPFOR::Argument*> live2, dead2;
|
||||||
vector<SAPFOR::Argument*> formal_parameters2 = formal_parameters;
|
vector<SAPFOR::Argument*> formal_parameters2 = formal_parameters;
|
||||||
vector<fcall> fcalls2;
|
vector<fcall> fcalls2;
|
||||||
|
|
||||||
buildUseDef2(bb, live2, dead2, formal_parameters2, fcalls2, funcByName);
|
buildUseDef2(getBlock(), live2, dead2, formal_parameters2, fcalls2, funcByName);
|
||||||
|
|
||||||
bool err = false;
|
bool err = false;
|
||||||
|
|
||||||
for (auto& l1 : live1) {
|
for (auto& l1 : live1) {
|
||||||
if (live2.find(l1) == live2.end()) {
|
if (live2.find(l1) == live2.end()) {
|
||||||
__spf_print(1, "bb %d use %s >> 1\n", bb->getNumber(), l1->getValue().c_str());
|
__spf_print(1, "bb %d use %s >> 1\n", getBlock()->getNumber(), l1->getValue().c_str());
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& l2 : live2) {
|
for (auto& l2 : live2) {
|
||||||
if (live1.find(l2) == live1.end()) {
|
if (live1.find(l2) == live1.end()) {
|
||||||
__spf_print(1, "bb %d use %s >> 2\n", bb->getNumber(), l2->getValue().c_str());
|
__spf_print(1, "bb %d use %s >> 2\n", getBlock()->getNumber(), l2->getValue().c_str());
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -259,14 +274,14 @@ struct BasicBlockNode
|
|||||||
|
|
||||||
for (auto& l1 : dead1) {
|
for (auto& l1 : dead1) {
|
||||||
if (dead2.find(l1) == dead2.end()) {
|
if (dead2.find(l1) == dead2.end()) {
|
||||||
__spf_print(1, "bb %d dead %s >> 1\n", bb->getNumber(), l1->getValue().c_str());
|
__spf_print(1, "bb %d dead %s >> 1\n", getBlock()->getNumber(), l1->getValue().c_str());
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& l2 : dead2) {
|
for (auto& l2 : dead2) {
|
||||||
if (dead1.find(l2) == dead1.end()) {
|
if (dead1.find(l2) == dead1.end()) {
|
||||||
__spf_print(1, "bb %d dead %s >> 2\n", bb->getNumber(), l2->getValue().c_str());
|
__spf_print(1, "bb %d dead %s >> 2\n", getBlock()->getNumber(), l2->getValue().c_str());
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,7 +289,7 @@ struct BasicBlockNode
|
|||||||
err |= dead1.size() != dead2.size();
|
err |= dead1.size() != dead2.size();
|
||||||
|
|
||||||
if (fcalls1.size() != fcalls2.size()) {
|
if (fcalls1.size() != fcalls2.size()) {
|
||||||
__spf_print(1, "bb %d different fcall sizes: 1: %d, w: %d\n", bb->getNumber(), fcalls1.size(), fcalls2.size());
|
__spf_print(1, "bb %d different fcall sizes: 1: %d, w: %d\n", getBlock()->getNumber(), fcalls1.size(), fcalls2.size());
|
||||||
|
|
||||||
err = true;
|
err = true;
|
||||||
}
|
}
|
||||||
@@ -310,7 +325,7 @@ struct BasicBlockNode
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(err)
|
if (err)
|
||||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
live = live1;
|
live = live1;
|
||||||
@@ -320,64 +335,24 @@ struct BasicBlockNode
|
|||||||
for (auto& fc : fcalls1)
|
for (auto& fc : fcalls1)
|
||||||
fcalls.push_back(fc);
|
fcalls.push_back(fc);
|
||||||
|
|
||||||
|
|
||||||
for (SAPFOR::Argument* arg : live)
|
for (SAPFOR::Argument* arg : live)
|
||||||
bb->addLiveIn({ { arg, { bb } } });
|
getBlock()->addLiveIn({ { arg, { getBlock() } } });
|
||||||
|
|
||||||
rollback = {};
|
|
||||||
ignore_rollback = {};
|
|
||||||
next_blocks = {};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void updateLive()
|
class LiveVarAnalysis : public BackwardDataFlowAnalysis<map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>, LiveVarAnalysisNode> {
|
||||||
{
|
protected:
|
||||||
bool in_changed = false, out_changed = false;
|
vector<SAPFOR::Argument*>& formal_parameters;
|
||||||
int in_max_cnt = CNT_NOTINIT, out_max_cnt = CNT_NOTINIT;
|
vector<fcall>& fcalls;
|
||||||
for (auto next : next_blocks)
|
const map<string, FuncInfo*>& funcByName;
|
||||||
{
|
|
||||||
if (out_cnt < next->in_cnt)
|
|
||||||
{
|
|
||||||
for (const auto& byArg : next->bb->getLiveIn())
|
|
||||||
{
|
|
||||||
bool inserted = bb->addLiveOut({ byArg });
|
|
||||||
out_changed |= inserted;
|
|
||||||
|
|
||||||
if (inserted)
|
LiveVarAnalysisNode* createNode(SAPFOR::BasicBlock* block) override {
|
||||||
{
|
return new LiveVarAnalysisNode(block, formal_parameters, fcalls, funcByName);
|
||||||
if (next->in_cnt > out_max_cnt)
|
};
|
||||||
out_max_cnt = next->in_cnt;
|
public:
|
||||||
|
LiveVarAnalysis(vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||||
if (live.find(byArg.first) == live.end() && dead.find(byArg.first) == dead.end())
|
const map<string, FuncInfo*>& funcByName) : formal_parameters(formal_parameters), fcalls(fcalls), funcByName(funcByName)
|
||||||
{
|
{ };
|
||||||
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; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||||
@@ -607,136 +582,6 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use,
|
|||||||
def = tmp_def;
|
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
|
// prints info about live variables
|
||||||
void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
|
void doDumpLive(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project)
|
||||||
@@ -912,7 +757,7 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
|||||||
vector<set<FuncInfo*>> scc;
|
vector<set<FuncInfo*>> scc;
|
||||||
vector<set<FuncInfo*>> callLvls = groupByCallDependencies(callDeps, 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;
|
map<string, vector<SAPFOR::Argument*>> func_to_parameters;
|
||||||
|
|
||||||
list<vector<fcall>> live_for_fcalls;
|
list<vector<fcall>> live_for_fcalls;
|
||||||
@@ -933,8 +778,9 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
|||||||
|
|
||||||
auto& params = func_to_parameters[byFunc->funcName] = vector<SAPFOR::Argument*>(byFunc->funcParams.countOfPars, NULL);
|
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));
|
LiveVarAnalysis* analysis_object = (func_to_analysis_object[byFunc->funcName] = new LiveVarAnalysis(params, curr_fcalls, funcByName));
|
||||||
analyzeSequence(blocks_with_cnt);
|
analysis_object->fit(itCFG->second);
|
||||||
|
analysis_object->analyze();
|
||||||
|
|
||||||
fillLiveDeadArgs(byFunc, itCFG->second);
|
fillLiveDeadArgs(byFunc, itCFG->second);
|
||||||
}
|
}
|
||||||
@@ -964,8 +810,8 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
|||||||
|
|
||||||
for (const auto& func : assembled_fcalls)
|
for (const auto& func : assembled_fcalls)
|
||||||
{
|
{
|
||||||
auto func_it = func_to_blocks_with_cnt.find(func.first->funcName);
|
auto func_it = func_to_analysis_object.find(func.first->funcName);
|
||||||
if (func_it == func_to_blocks_with_cnt.end())
|
if (func_it == func_to_analysis_object.end())
|
||||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||||
|
|
||||||
auto param_it = func_to_parameters.find(func.first->funcName);
|
auto param_it = func_to_parameters.find(func.first->funcName);
|
||||||
@@ -987,14 +833,14 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set<BasicBlockNode*> exits;
|
set<LiveVarAnalysisNode*> exits;
|
||||||
int max_cnt = CNT_NOTINIT;
|
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);
|
exits.insert(block);
|
||||||
if (block->out_cnt > max_cnt)
|
if (block->getInCnt() > max_cnt)
|
||||||
max_cnt = block->out_cnt;
|
max_cnt = block->getInCnt();
|
||||||
}
|
}
|
||||||
|
|
||||||
max_cnt++;
|
max_cnt++;
|
||||||
@@ -1003,23 +849,22 @@ void runLiveVariableAnalysis(const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>&
|
|||||||
{
|
{
|
||||||
for (const auto& byArg : live_after)
|
for (const auto& byArg : live_after)
|
||||||
{
|
{
|
||||||
if (exit->bb->addLiveOut({ byArg }))
|
if (exit->addIn({ byArg }))
|
||||||
{
|
{
|
||||||
exit->out_cnt = max_cnt;
|
exit->setInCnt(max_cnt);
|
||||||
if (exit->live.find(byArg.first) == exit->live.end() && exit->dead.find(byArg.first) == exit->dead.end())
|
if(exit->forwardData({ byArg }))
|
||||||
if (exit->bb->addLiveIn({ byArg }))
|
exit->setOutCnt(max_cnt);
|
||||||
exit->in_cnt = max_cnt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we can update live sets in all blocks
|
// 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)
|
for (const auto& byFunc : func_to_analysis_object)
|
||||||
freeBlocksWithCnt(nodeByFunc.second);
|
delete byFunc.second;
|
||||||
|
|
||||||
for (auto& byFunc : CFGraph_for_project)
|
for (auto& byFunc : CFGraph_for_project)
|
||||||
for (auto& byBlock : byFunc.second)
|
for (auto& byBlock : byFunc.second)
|
||||||
|
|||||||
Reference in New Issue
Block a user