improve def/use analysis

This commit is contained in:
Михаил Кочармин
2024-01-01 18:08:56 +03:00
parent 85aaee900b
commit 168e190c7a

View File

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