improve def/use analysis
This commit is contained in:
@@ -172,13 +172,17 @@ public:
|
||||
void make_dead(SAPFOR::Argument* arg)
|
||||
{
|
||||
if (arg->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || arg->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
||||
commons_dead_after.insert(arg);
|
||||
{
|
||||
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();
|
||||
dead_after.insert(idx);
|
||||
if (live_after.find(idx) == live_after.end())
|
||||
dead_after.insert(idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +201,10 @@ static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName);
|
||||
|
||||
static void buildUseDef2(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
const map<string, FuncInfo*>& funcByName);
|
||||
|
||||
enum
|
||||
{
|
||||
CNT_NOTINIT = 0
|
||||
@@ -218,7 +226,101 @@ struct BasicBlockNode
|
||||
bb = block;
|
||||
out_cnt = in_cnt = CNT_NOTINIT;
|
||||
|
||||
buildUseDef(bb, live, dead, formal_parameters, fcalls, funcByName);
|
||||
set<SAPFOR::Argument*> live1, dead1;
|
||||
vector<SAPFOR::Argument*> formal_parameters1 = formal_parameters;
|
||||
vector<fcall> fcalls1;
|
||||
|
||||
buildUseDef(bb, live1, dead1, formal_parameters1, fcalls1, funcByName);
|
||||
|
||||
|
||||
set<SAPFOR::Argument*> live2, dead2;
|
||||
vector<SAPFOR::Argument*> formal_parameters2 = formal_parameters;
|
||||
vector<fcall> fcalls2;
|
||||
|
||||
buildUseDef2(bb, live2, dead2, formal_parameters2, fcalls2, funcByName);
|
||||
|
||||
bool err = false;
|
||||
|
||||
for (auto& l1 : live1) {
|
||||
if (live2.find(l1) == live2.end()) {
|
||||
__spf_print(1, "bb %d use %s >> 1\n", bb->getNumber(), l1->getValue().c_str());
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& l2 : live2) {
|
||||
if (live1.find(l2) == live1.end()) {
|
||||
__spf_print(1, "bb %d use %s >> 2\n", bb->getNumber(), l2->getValue().c_str());
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
|
||||
err |= live1.size() != live2.size();
|
||||
|
||||
for (auto& l1 : dead1) {
|
||||
if (dead2.find(l1) == dead2.end()) {
|
||||
__spf_print(1, "bb %d dead %s >> 1\n", bb->getNumber(), l1->getValue().c_str());
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& l2 : dead2) {
|
||||
if (dead1.find(l2) == dead1.end()) {
|
||||
__spf_print(1, "bb %d dead %s >> 2\n", bb->getNumber(), l2->getValue().c_str());
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
|
||||
err |= dead1.size() != dead2.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());
|
||||
|
||||
err = true;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < fcalls1.size(); i++) {
|
||||
auto& c1 = fcalls1[i];
|
||||
auto& c2 = fcalls2[fcalls1.size() - i - 1];
|
||||
|
||||
if (c1.func->funcName != c2.func->funcName) {
|
||||
__spf_print(1, "different fnames %s, %s\n", c1.func->funcName.c_str(), c2.func->funcName.c_str());
|
||||
err = true;
|
||||
}
|
||||
|
||||
if (c1.live_after != c2.live_after) {
|
||||
__spf_print(1, "different live_after\n");
|
||||
err = true;
|
||||
}
|
||||
|
||||
if (c1.dead_after != c2.dead_after) {
|
||||
__spf_print(1, "different dead_after\n");
|
||||
err = true;
|
||||
}
|
||||
|
||||
if (c1.commons_dead_after != c2.commons_dead_after) {
|
||||
__spf_print(1, "different commons_dead_after\n");
|
||||
err = true;
|
||||
}
|
||||
|
||||
if (c1.commons_live_after != c2.commons_live_after) {
|
||||
__spf_print(1, "different commons_live_after\n");
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(err)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
live = live1;
|
||||
dead = dead1;
|
||||
formal_parameters = formal_parameters1;
|
||||
|
||||
for (auto& fc : fcalls1)
|
||||
fcalls.push_back(fc);
|
||||
|
||||
|
||||
for (SAPFOR::Argument* arg : live)
|
||||
bb->addLiveIn({ { arg, { bb } } });
|
||||
|
||||
@@ -278,6 +380,130 @@ struct BasicBlockNode
|
||||
bool newerThan(const BasicBlockNode* block) const { return in_cnt > block->out_cnt; }
|
||||
};
|
||||
|
||||
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
|
||||
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
|
||||
vector<SAPFOR::Argument*>& formal_parameters, vector<fcall>& fcalls,
|
||||
vector<SAPFOR::Argument*>& lastParamRef, int& last_param_ref_index, int& last_param_ref_size,
|
||||
string& fName,
|
||||
const map<string, FuncInfo*>& funcByName)
|
||||
{
|
||||
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))
|
||||
{
|
||||
res_arg = instr->getArg1();
|
||||
set<SAPFOR::Argument*> instr_args = { instr->getResult(), instr->getArg2() };
|
||||
insertIfVar(instr_args.begin(), instr_args.end(), args);
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::PARAM)
|
||||
{
|
||||
lastParamRef[last_param_ref_index--] = instr->getArg1();
|
||||
}
|
||||
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
|
||||
{
|
||||
res_arg = instr->getResult();
|
||||
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
//skip
|
||||
return;
|
||||
}
|
||||
|
||||
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(fcall(func_it->second, block, lastParamRef));
|
||||
|
||||
auto r_it = fcalls.rbegin();
|
||||
auto r_end = fcalls.rend();
|
||||
|
||||
|
||||
for (auto e : def)
|
||||
r_it->make_dead(e);
|
||||
|
||||
for (auto e : use)
|
||||
r_it->make_live(e, block);
|
||||
}
|
||||
|
||||
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_index = 0;
|
||||
last_param_ref_size = 0;
|
||||
|
||||
lastParamRef.clear();
|
||||
}
|
||||
|
||||
if (res_arg && res_arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
||||
res.insert(res_arg);
|
||||
|
||||
for (auto e : res)
|
||||
{
|
||||
def.insert(e);
|
||||
use.erase(e);
|
||||
}
|
||||
|
||||
for (auto e : args) {
|
||||
use.insert(e);
|
||||
def.erase(e);
|
||||
}
|
||||
}
|
||||
|
||||
//Build use and def sets of block. Result are stored in use and def
|
||||
static void buildUseDef2(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*> 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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//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,
|
||||
|
||||
Reference in New Issue
Block a user