refactored transformation: added folders for each transformation
This commit is contained in:
631
src/Transformations/DeadCodeRemoving/dead_code.cpp
Normal file
631
src/Transformations/DeadCodeRemoving/dead_code.cpp
Normal file
@@ -0,0 +1,631 @@
|
||||
#include "dead_code.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
using std::map;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
|
||||
using std::remove_if;
|
||||
|
||||
#define PRINT_USELESS_STATEMENTS 1
|
||||
#define DEBUG_IR 0
|
||||
|
||||
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*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
|
||||
string& fName, const map<string, FuncInfo*>& funcByName,
|
||||
bool& useful, bool& last_stack_op_useful,
|
||||
set<SAPFOR::Argument*>& usedByThisBlock)
|
||||
{
|
||||
set<SAPFOR::Argument*> res, args;
|
||||
bool last_stack_op;
|
||||
|
||||
vector<LIVE_VARIABLES::LiveDeadVarsForCall> fcalls;
|
||||
|
||||
getUseDefForInstruction(block, instr,
|
||||
args, res,
|
||||
formal_parameters, fcalls,
|
||||
arg_stack, arg_stack_index, arg_stack_size,
|
||||
last_stack_op,
|
||||
fName, funcByName,
|
||||
false
|
||||
);
|
||||
|
||||
const auto instr_operation = instr->getOperation();
|
||||
|
||||
if (!useful)
|
||||
{
|
||||
for (SAPFOR::Argument* r : res)
|
||||
{
|
||||
if (use.find(r) != use.end() ||
|
||||
r->getMemType() != SAPFOR::CFG_MEM_TYPE::LOCAL_ ||
|
||||
!(r->getType() == SAPFOR::CFG_ARG_TYPE::VAR || r->getType() == SAPFOR::CFG_ARG_TYPE::REG))
|
||||
{
|
||||
useful = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!useful)
|
||||
{
|
||||
static const 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::IO_PARAM
|
||||
};
|
||||
|
||||
if (always_useful.find(instr_operation) != always_useful.end())
|
||||
useful = true;
|
||||
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
{
|
||||
auto func_it = funcByName.find(instr->getArg1()->getValue());
|
||||
useful |= func_it == funcByName.end() || !(func_it->second->isPure);
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::PARAM ||
|
||||
instr_operation == SAPFOR::CFG_OP::REF)
|
||||
useful |= last_stack_op_useful;
|
||||
}
|
||||
|
||||
if (useful)
|
||||
{
|
||||
if (instr_operation == SAPFOR::CFG_OP::F_CALL ||
|
||||
instr_operation == SAPFOR::CFG_OP::LOAD ||
|
||||
instr_operation == SAPFOR::CFG_OP::STORE)
|
||||
last_stack_op_useful = true;
|
||||
|
||||
for (auto e : res)
|
||||
{
|
||||
def.insert(e);
|
||||
use.erase(e);
|
||||
}
|
||||
|
||||
for (auto e : args)
|
||||
{
|
||||
use.insert(e);
|
||||
def.erase(e);
|
||||
}
|
||||
|
||||
usedByThisBlock.insert(args.begin(), args.end());
|
||||
}
|
||||
|
||||
if (last_stack_op)
|
||||
last_stack_op_useful = false;
|
||||
}
|
||||
|
||||
|
||||
//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, const map<string, FuncInfo*>& funcByName)
|
||||
{
|
||||
set<SAPFOR::Argument*> use_with_regs = use, def_with_regs = def;
|
||||
|
||||
vector<SAPFOR::Argument*> arg_stack;
|
||||
int arg_stack_index = 0, arg_stack_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,
|
||||
arg_stack, arg_stack_index, arg_stack_size,
|
||||
fName, funcByName,
|
||||
u, last_fcall_useful,
|
||||
usedByThisBlock
|
||||
);
|
||||
|
||||
useful[i] = u;
|
||||
}
|
||||
|
||||
use.insert(use_with_regs.begin(), use_with_regs.end());
|
||||
def.insert(def_with_regs.begin(), def_with_regs.end());
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
const map<string, FuncInfo*>& funcByName;
|
||||
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)
|
||||
{
|
||||
return getBlock()->addLiveOut(data);
|
||||
}
|
||||
|
||||
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
return getBlock()->addLiveIn(data);
|
||||
}
|
||||
|
||||
bool updateState()
|
||||
{
|
||||
bool updated = false;
|
||||
|
||||
if (!useful_block)
|
||||
updated |= updateNextNotEmpty();
|
||||
|
||||
if (!useful_block)
|
||||
{
|
||||
if (next_notempty_in != next_notempty_out)
|
||||
{
|
||||
updated = true;
|
||||
next_notempty_out = next_notempty_in;
|
||||
}
|
||||
}
|
||||
|
||||
updated |= updateJumpStatus();
|
||||
|
||||
if(updated)
|
||||
this->forwardData({ });
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
DATA_FLOW_UPD_STATUS forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
|
||||
{
|
||||
bool inserted_prop = false, inserted_gen = 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, funcByName);
|
||||
|
||||
auto in = bb->getLiveIn(), out = bb->getLiveOut();
|
||||
|
||||
for (SAPFOR::Argument* arg : use)
|
||||
{
|
||||
if(arg && (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR || arg->getType() == SAPFOR::CFG_ARG_TYPE::REG))
|
||||
{
|
||||
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_prop |= 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_gen |= bb->addLiveIn({ { arg, { bb } } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!useful_block)
|
||||
{
|
||||
for(bool status : useful)
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
useful_block = true;
|
||||
|
||||
inserted_gen = true;
|
||||
next_notempty_out = { this };
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(inserted_gen)
|
||||
return DATA_FLOW_UPD_STATUS::GENERATED;
|
||||
else if(inserted_prop)
|
||||
return DATA_FLOW_UPD_STATUS::PROPAGATED;
|
||||
|
||||
return DATA_FLOW_UPD_STATUS::NO_CHANGE;
|
||||
}
|
||||
|
||||
DeadCodeAnalysisNode(SAPFOR::BasicBlock* block,
|
||||
vector<SAPFOR::Argument*>& formal_parameters,
|
||||
const map<string, FuncInfo*>& funcByName)
|
||||
:
|
||||
formal_parameters(formal_parameters),
|
||||
funcByName(funcByName)
|
||||
{
|
||||
setBlock(block);
|
||||
useful.resize(block->getInstructions().size(), false);
|
||||
this->forwardData({ });
|
||||
}
|
||||
|
||||
const vector<bool>& getResult() { return useful; }
|
||||
};
|
||||
|
||||
class DeadCodeAnalysis : public BackwardDataFlowAnalysis<DeadCodeAnalysisNode>
|
||||
{
|
||||
protected:
|
||||
vector<SAPFOR::Argument*>& formal_parameters;
|
||||
const map<string, FuncInfo*>& funcByName;
|
||||
|
||||
DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override
|
||||
{
|
||||
return new DeadCodeAnalysisNode(block, formal_parameters, funcByName);
|
||||
}
|
||||
public:
|
||||
DeadCodeAnalysis(vector<SAPFOR::Argument*>& formal_parameters,
|
||||
const map<string, FuncInfo*>& funcByName)
|
||||
:
|
||||
formal_parameters(formal_parameters),
|
||||
funcByName(funcByName)
|
||||
{ }
|
||||
};
|
||||
|
||||
static bool hasCalls(SgExpression* ex)
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == FUNC_CALL)
|
||||
return true;
|
||||
return hasCalls(ex->lhs()) || hasCalls(ex->rhs());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: add check for side effects for function calls
|
||||
static bool hasCalls(SgStatement* stat)
|
||||
{
|
||||
if (stat->variant() == FOR_NODE)
|
||||
{
|
||||
auto forSt = isSgForStmt(stat);
|
||||
return hasCalls(forSt->start()) || hasCalls(forSt->end()) || hasCalls(forSt->step());
|
||||
}
|
||||
else
|
||||
return hasCalls(stat->expr(0)) || hasCalls(stat->expr(1)) || hasCalls(stat->expr(2));
|
||||
}
|
||||
|
||||
static void moveComment(SgStatement* stat)
|
||||
{
|
||||
const char* comm = stat->comments();
|
||||
if (comm)
|
||||
{
|
||||
SgStatement* next = stat->lastNodeOfStmt()->lexNext();
|
||||
if (next)
|
||||
{
|
||||
const char* commNext = next->comments();
|
||||
if (commNext)
|
||||
{
|
||||
string newComm(comm);
|
||||
newComm += commNext;
|
||||
|
||||
next->delComments();
|
||||
next->addComment(newComm.c_str());
|
||||
}
|
||||
else
|
||||
next->addComment(comm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int removeDeadCode(SgStatement* func,
|
||||
const map<string, vector<FuncInfo*>>& allFuncs,
|
||||
const map<string, CommonBlock*>& commonBlocks,
|
||||
SgStatement* intervalDelStart, SgStatement* intervalDelEnd)
|
||||
{
|
||||
int countOfTransform = 0;
|
||||
if (intervalDelStart && !intervalDelEnd || !intervalDelStart && intervalDelEnd)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
SgProgHedrStmt* prog = isSgProgHedrStmt(func);
|
||||
|
||||
if (intervalDelStart)
|
||||
if (intervalDelStart->lineNumber() < prog->lineNumber() || intervalDelStart->lineNumber() > prog->lastNodeOfStmt()->lineNumber())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (intervalDelEnd)
|
||||
if (intervalDelEnd->lineNumber() < prog->lineNumber() || intervalDelEnd->lineNumber() > prog->lastNodeOfStmt()->lineNumber())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
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__);
|
||||
|
||||
auto& cfg_pair = *(cfg.begin());
|
||||
|
||||
// delete unreachable blocks
|
||||
|
||||
set<SAPFOR::BasicBlock*> reachable;
|
||||
|
||||
for (auto b : cfg_pair.second)
|
||||
if(b->getInstructions().front()->isHeader() ||
|
||||
b->getInstructions().front()->getInstruction()->getOperation() == SAPFOR::CFG_OP::ENTRY)
|
||||
reachable.insert(b);
|
||||
|
||||
set<SAPFOR::BasicBlock*> worklist = reachable;
|
||||
while (worklist.size() != 0)
|
||||
{
|
||||
set<SAPFOR::BasicBlock*> to_insert;
|
||||
|
||||
for(auto b : worklist)
|
||||
for(auto next: b->getNext())
|
||||
if(reachable.insert(next).second)
|
||||
to_insert.insert(next);
|
||||
|
||||
worklist = to_insert;
|
||||
}
|
||||
|
||||
auto remove_unreachable_it = remove_if(cfg_pair.second.begin(), cfg_pair.second.end(),
|
||||
[&reachable](SAPFOR::BasicBlock* b)
|
||||
{
|
||||
if (reachable.find(b) == reachable.end())
|
||||
{
|
||||
for(auto next: b->getNext())
|
||||
if(reachable.find(next) != reachable.end())
|
||||
next->removePrev(b);
|
||||
|
||||
delete b;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
reachable.clear();
|
||||
|
||||
cfg_pair.second.erase(remove_unreachable_it, cfg_pair.second.end());
|
||||
|
||||
#if DEBUG_IR
|
||||
dumpCFG({ cfg_pair }, false);
|
||||
#endif
|
||||
// detect useless code
|
||||
vector<SAPFOR::Argument*> func_parameters(cfg_pair.first->funcParams.countOfPars, NULL);
|
||||
|
||||
map<string, FuncInfo*> funcByName;
|
||||
|
||||
for (auto& byFile : allFuncs)
|
||||
for (auto byFunc : byFile.second)
|
||||
funcByName[byFunc->funcName] = byFunc;
|
||||
|
||||
DeadCodeAnalysis analysis_object(func_parameters, funcByName);
|
||||
|
||||
analysis_object.fit(cfg_pair.second);
|
||||
analysis_object.analyze();
|
||||
|
||||
// detect dead statements
|
||||
|
||||
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)
|
||||
stmt = stmt->controlParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove dead statements
|
||||
static const set<int> removable =
|
||||
{
|
||||
ASSIGN_STAT,
|
||||
PROC_STAT,
|
||||
WRITE_STAT,
|
||||
READ_STAT
|
||||
};
|
||||
|
||||
vector<SgStatement*> remove;
|
||||
SgStatement* start = intervalDelStart ? intervalDelStart : func;
|
||||
SgStatement* end = intervalDelEnd ? intervalDelEnd : func->lastNodeOfStmt();
|
||||
|
||||
for (auto st = start; st != end; st = st->lexNext())
|
||||
{
|
||||
const int var = st->variant();
|
||||
if (removable.find(var) != removable.end() && useful.find(st) == useful.end())
|
||||
{
|
||||
remove.push_back(st);
|
||||
st = st->lastNodeOfStmt();
|
||||
}
|
||||
|
||||
if (var == CONTAINS_STMT)
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto& rem : remove)
|
||||
{
|
||||
__spf_print(PRINT_USELESS_STATEMENTS, "[Useless statement on line %d and file %s]\n", rem->lineNumber(), rem->fileName());
|
||||
|
||||
auto cp = rem->controlParent();
|
||||
if (cp->variant() == LOGIF_NODE)
|
||||
{
|
||||
if (hasCalls(cp))
|
||||
{
|
||||
((SgLogIfStmt*)cp)->convertLogicIf();
|
||||
rem->deleteStmt();
|
||||
}
|
||||
else
|
||||
{
|
||||
moveLabelBefore(cp);
|
||||
moveComment(cp);
|
||||
cp->deleteStmt();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
moveLabelBefore(rem);
|
||||
moveComment(rem);
|
||||
rem->deleteStmt();
|
||||
}
|
||||
}
|
||||
countOfTransform += remove.size();
|
||||
|
||||
//remove empty blocks
|
||||
do
|
||||
{
|
||||
remove.clear();
|
||||
for (auto st = start; st != end; st = st->lexNext())
|
||||
{
|
||||
const int var = st->variant();
|
||||
if ((var == FOR_NODE || var == WHILE_NODE || var == SWITCH_NODE) &&
|
||||
st->lexNext()->variant() == CONTROL_END)
|
||||
{
|
||||
if (!hasCalls(st))
|
||||
remove.push_back(st);
|
||||
}
|
||||
else if (var == IF_NODE)
|
||||
{
|
||||
if (!hasCalls(st))
|
||||
{
|
||||
bool hasCalls_ = false;
|
||||
SgStatement* ifS = st;
|
||||
while (ifS->lexNext()->variant() == ELSEIF_NODE)
|
||||
{
|
||||
hasCalls_ |= hasCalls(ifS->lexNext());
|
||||
ifS = ifS->lexNext();
|
||||
}
|
||||
|
||||
SgStatement* lastNode = ifS->lastNodeOfStmt();
|
||||
ifS = ifS->lexNext();
|
||||
|
||||
while (ifS->variant() == CONTROL_END && ifS != lastNode)
|
||||
ifS = ifS->lexNext();
|
||||
|
||||
if (ifS == lastNode && !hasCalls_)
|
||||
remove.push_back(st);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: other block statements
|
||||
|
||||
if (var == CONTAINS_STMT)
|
||||
break;
|
||||
}
|
||||
|
||||
bool mainRemoved = false;
|
||||
for (auto& rem : remove)
|
||||
{
|
||||
__spf_print(PRINT_USELESS_STATEMENTS, "[Useless block statement on line %d and file %s]\n", rem->lineNumber(), rem->fileName());
|
||||
moveLabelBefore(rem);
|
||||
moveComment(rem);
|
||||
rem->deleteStmt();
|
||||
if (rem == start)
|
||||
mainRemoved = true;
|
||||
}
|
||||
countOfTransform += remove.size();
|
||||
if (mainRemoved)
|
||||
break;
|
||||
} while (remove.size());
|
||||
|
||||
deleteCFG(cfg);
|
||||
return countOfTransform;
|
||||
}
|
||||
15
src/Transformations/DeadCodeRemoving/dead_code.h
Normal file
15
src/Transformations/DeadCodeRemoving/dead_code.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#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"
|
||||
|
||||
int removeDeadCode(SgStatement* func,
|
||||
const std::map<std::string, std::vector<FuncInfo*>>&allFuncs,
|
||||
const std::map<std::string, CommonBlock*>& commonBlocks,
|
||||
SgStatement* intervalDelStart = NULL, SgStatement* intervalDelEnd = NULL);
|
||||
Reference in New Issue
Block a user