add REMOVE_DEAD_CODE_AND_UNPARSE (debug) pass
This commit is contained in:
@@ -161,6 +161,8 @@ set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp
|
|||||||
_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp
|
_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp
|
||||||
_src/ParallelizationRegions/resolve_par_reg_conflicts.h)
|
_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
|
set(TR_CP _src/Transformations/checkpoints.cpp
|
||||||
_src/Transformations/checkpoints.h)
|
_src/Transformations/checkpoints.h)
|
||||||
set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp
|
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)
|
_src/Transformations/convert_to_c.h)
|
||||||
|
|
||||||
set(TRANSFORMS
|
set(TRANSFORMS
|
||||||
|
${TR_DEAD_CODE}
|
||||||
${TR_CP}
|
${TR_CP}
|
||||||
${TR_VECTOR}
|
${TR_VECTOR}
|
||||||
${TR_ENDDO_LOOP}
|
${TR_ENDDO_LOOP}
|
||||||
@@ -414,6 +417,7 @@ 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 (CFGraph\\DataFlow FILES ${DATA_FLOW})
|
||||||
|
|
||||||
|
source_group (Transformations\\DeadCodeRemoving FILES ${TR_DEAD_CODE})
|
||||||
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})
|
||||||
source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP})
|
source_group (Transformations\\LoopEndDoConverter FILES ${TR_ENDDO_LOOP})
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace SAPFOR
|
|||||||
|
|
||||||
bool addLive(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add, bool in);
|
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;
|
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLive(bool in) const;
|
||||||
|
bool removeLive(SAPFOR::Argument* to_remove, bool in);
|
||||||
public:
|
public:
|
||||||
BasicBlock() { num = lastNumBlock++; }
|
BasicBlock() { num = lastNumBlock++; }
|
||||||
BasicBlock(IR_Block* item);
|
BasicBlock(IR_Block* item);
|
||||||
@@ -72,6 +73,9 @@ namespace SAPFOR
|
|||||||
bool addLiveIn(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, true); };
|
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 addLiveOut(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add) { return addLive(to_add, 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::set<SAPFOR::BasicBlock*>> getLiveIn() const { return getLive(true); };
|
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); };
|
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLiveOut() const { return getLive(false); };
|
||||||
void compressLives();
|
void compressLives();
|
||||||
|
|||||||
@@ -97,6 +97,37 @@ namespace SAPFOR
|
|||||||
return inserted;
|
return inserted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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*, set<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
|
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> BasicBlock::getLive(bool in) const {
|
||||||
auto& current_set = in ? live_in : live_out;
|
auto& current_set = in ? live_in : live_out;
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
#include "Transformations/private_removing.h"
|
#include "Transformations/private_removing.h"
|
||||||
#include "Transformations/fix_common_blocks.h"
|
#include "Transformations/fix_common_blocks.h"
|
||||||
#include "Transformations/convert_to_c.h"
|
#include "Transformations/convert_to_c.h"
|
||||||
|
#include "Transformations/dead_code.h"
|
||||||
|
|
||||||
#include "RenameSymbols/rename_symbols.h"
|
#include "RenameSymbols/rename_symbols.h"
|
||||||
#include "ProjectParameters/projectParameters.h"
|
#include "ProjectParameters/projectParameters.h"
|
||||||
@@ -1169,6 +1170,12 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne
|
|||||||
covertToC(file);
|
covertToC(file);
|
||||||
else if (curr_regime == INSERT_NO_DISTR_FLAGS_FROM_GUI)
|
else if (curr_regime == INSERT_NO_DISTR_FLAGS_FROM_GUI)
|
||||||
addPrivatesToArraysFromGUI(file, declaredArrays, distrStateFromGUI);
|
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)
|
else if (curr_regime == TEST_PASS)
|
||||||
{
|
{
|
||||||
//test pass
|
//test pass
|
||||||
@@ -2515,6 +2522,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam
|
|||||||
findFunctionsToInclude(true);
|
findFunctionsToInclude(true);
|
||||||
break;
|
break;
|
||||||
// all these cases run UNPARSE_FILE after
|
// all these cases run UNPARSE_FILE after
|
||||||
|
case REMOVE_DEAD_CODE_AND_UNPARSE:
|
||||||
case RENAME_SYMBOLS:
|
case RENAME_SYMBOLS:
|
||||||
case RESOLVE_PAR_REGIONS:
|
case RESOLVE_PAR_REGIONS:
|
||||||
case CREATE_PARALLEL_REGIONS:
|
case CREATE_PARALLEL_REGIONS:
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ enum passes {
|
|||||||
BUILD_IR,
|
BUILD_IR,
|
||||||
LIVE_ANALYSIS_IR,
|
LIVE_ANALYSIS_IR,
|
||||||
PRIVATE_ANALYSIS_IR,
|
PRIVATE_ANALYSIS_IR,
|
||||||
|
REMOVE_DEAD_CODE_AND_UNPARSE,
|
||||||
|
|
||||||
FIX_COMMON_BLOCKS,
|
FIX_COMMON_BLOCKS,
|
||||||
REMOVE_OMP_DIRS,
|
REMOVE_OMP_DIRS,
|
||||||
@@ -343,6 +344,7 @@ static void setPassValues()
|
|||||||
passNames[CALL_GRAPH_IR] = "CALL_GRAPH_IR";
|
passNames[CALL_GRAPH_IR] = "CALL_GRAPH_IR";
|
||||||
passNames[LIVE_ANALYSIS_IR] = "LIVE_ANALYSIS_IR";
|
passNames[LIVE_ANALYSIS_IR] = "LIVE_ANALYSIS_IR";
|
||||||
passNames[PRIVATE_ANALYSIS_IR] = "PRIVATE_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[FIX_COMMON_BLOCKS] = "FIX_COMMON_BLOCKS";
|
||||||
passNames[REMOVE_OMP_DIRS] = "REMOVE_OMP_DIRS";
|
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::fcall> 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*, set<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*, set<SAPFOR::BasicBlock*>> getIn() {
|
||||||
|
return getBlock()->getLiveOut();
|
||||||
|
};
|
||||||
|
|
||||||
|
map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>> getOut() {
|
||||||
|
return getBlock()->getLiveIn();
|
||||||
|
};
|
||||||
|
|
||||||
|
bool addIn(const map<SAPFOR::Argument*, set<SAPFOR::BasicBlock*>>& data) {
|
||||||
|
bool inserted = getBlock()->addLiveOut(data);
|
||||||
|
|
||||||
|
if (!useful_block)
|
||||||
|
inserted |= updateNextNotEmpty();
|
||||||
|
|
||||||
|
inserted |= updateJumpStatus();
|
||||||
|
|
||||||
|
return inserted;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
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*, set<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(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,
|
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,
|
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,
|
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