dead_code_removing (Новый проход) #21

Merged
Alexander_KS merged 6 commits from dead_code_removing into master 2024-01-12 18:45:36 +00:00
8 changed files with 502 additions and 1 deletions
Showing only changes of commit 14219cdfd5 - Show all commits

View File

@@ -160,7 +160,9 @@ set(PARALLEL_REG _src/ParallelizationRegions/ParRegions.cpp
_src/ParallelizationRegions/expand_extract_reg.h
_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp
_src/ParallelizationRegions/resolve_par_reg_conflicts.h)
set(TR_DEAD_CODE _src/Transformations/dead_code.cpp
_src/Transformations/dead_code.h)
set(TR_CP _src/Transformations/checkpoints.cpp
_src/Transformations/checkpoints.h)
set(TR_VECTOR _src/Transformations/array_assign_to_loop.cpp
@@ -191,6 +193,7 @@ set(TR_CONV _src/Transformations/convert_to_c.cpp
_src/Transformations/convert_to_c.h)
set(TRANSFORMS
${TR_DEAD_CODE}
${TR_CP}
${TR_VECTOR}
${TR_ENDDO_LOOP}
@@ -414,6 +417,7 @@ 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})

View File

@@ -33,6 +33,7 @@ namespace SAPFOR
bool addLive(const std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>>& to_add, bool in);
std::map<SAPFOR::Argument*, std::set<SAPFOR::BasicBlock*>> getLive(bool in) const;
bool removeLive(SAPFOR::Argument* to_remove, bool in);
public:
BasicBlock() { num = lastNumBlock++; }
BasicBlock(IR_Block* item);
@@ -71,6 +72,9 @@ namespace SAPFOR
*/
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 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*>> getLiveOut() const { return getLive(false); };

View File

@@ -97,6 +97,37 @@ namespace SAPFOR
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 {
auto& current_set = in ? live_in : live_out;

View File

@@ -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:

View File

@@ -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";

View 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;
}
}

View 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);

View File

@@ -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,