moved
This commit is contained in:
341
Sapfor/_src/DvmhRegions/ReadWriteAnalyzer.cpp
Normal file
341
Sapfor/_src/DvmhRegions/ReadWriteAnalyzer.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#include "leak_detector.h"
|
||||
#include "ReadWriteAnalyzer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ReadWriteAnalyzer::init(SgFile* forFile)
|
||||
{
|
||||
auto save = current_file->filename();
|
||||
|
||||
modified_pars = ReadWriteAnalyzer::load_modified_pars(funcInfo);
|
||||
for (int j = 0; j < forFile->numberOfFunctions(); ++j)
|
||||
{
|
||||
SgStatement* func_hdr = forFile->functions(j);
|
||||
SgStatement* last = func_hdr->lastNodeOfStmt();
|
||||
|
||||
for (SgStatement* runner = func_hdr->lexNext(); runner != last; runner = runner->lexNext())
|
||||
{
|
||||
// TODO: is it ok to skip all of them?
|
||||
if (!isSgExecutableStatement(runner) || isDVM_stat(runner) || isSPF_stat(runner))
|
||||
continue;
|
||||
|
||||
if (runner->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
VarUsages usages = findUsagesInStatement(runner);
|
||||
|
||||
auto it = usages_by_statement.find(runner);
|
||||
if (it != usages_by_statement.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
usages_by_statement[runner] = usages;
|
||||
}
|
||||
}
|
||||
initialized.insert(forFile->filename());
|
||||
|
||||
if (SgFile::switchToFile(save) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInStatement(SgStatement* st) const
|
||||
{
|
||||
// *special* statements, TODO: what i've missed?
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
return findUsagesInAssignment(st);
|
||||
|
||||
if (st->variant() == PROC_STAT)
|
||||
return findUsagesInFuncCall(st->expr(0), st->symbol()->identifier());
|
||||
else if (!isDVM_stat(st) && !isSPF_stat(st))
|
||||
{
|
||||
VarUsages st_usages;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
st_usages.extend(findUsagesInExpr(st->expr(i)));
|
||||
return st_usages;
|
||||
}
|
||||
return VarUsages();
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInAssignment(SgStatement* st) const
|
||||
{
|
||||
// load read & writes from the right part
|
||||
VarUsages usages = findUsagesInExpr(st->expr(1));
|
||||
|
||||
// load usages from array indexes
|
||||
VarUsages usages_in_arr_indexing = findUsagesInExpr(st->expr(1)->lhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
usages_in_arr_indexing = findUsagesInExpr(st->expr(1)->rhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
usages_in_arr_indexing = findUsagesInExpr(st->expr(0)->lhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
usages_in_arr_indexing = findUsagesInExpr(st->expr(0)->rhs());
|
||||
usages.extend(usages_in_arr_indexing);
|
||||
|
||||
// finally add explicitly modified var
|
||||
auto ex = st->expr(0);
|
||||
auto s = st->expr(0)->symbol();
|
||||
if (s && (ex->variant() == VAR_REF || isArrayRef(ex)))
|
||||
usages.insert_write(ex);
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInExpr(SgExpression* exp) const
|
||||
{
|
||||
VarUsages usages;
|
||||
|
||||
queue<SgExpression*> buf;
|
||||
buf.push(exp);
|
||||
|
||||
while (!buf.empty())
|
||||
{
|
||||
SgExpression* cur = buf.front();
|
||||
buf.pop();
|
||||
|
||||
if (!cur)
|
||||
continue;
|
||||
|
||||
const int e_type = cur->variant();
|
||||
|
||||
if (e_type == VAR_REF || isArrayRef(cur))
|
||||
usages.insert_read(cur);
|
||||
else if (e_type == FUNC_CALL)
|
||||
usages.extend(findUsagesInFuncCall(cur->lhs(), cur->symbol()->identifier()));
|
||||
|
||||
buf.push(cur->lhs());
|
||||
buf.push(cur->rhs());
|
||||
}
|
||||
return usages;
|
||||
}
|
||||
|
||||
void ReadWriteAnalyzer::findReadUsagesInExpression(SgExpression* ex, VarUsages& usages) const
|
||||
{
|
||||
if (ex)
|
||||
{
|
||||
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF)
|
||||
usages.insert_read(ex);
|
||||
|
||||
findReadUsagesInExpression(ex->lhs(), usages);
|
||||
findReadUsagesInExpression(ex->rhs(), usages);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: need to improve to MPI_* functions
|
||||
VarUsages ReadWriteAnalyzer::findUsagesInFuncCall(SgExpression* params_tree, const string& func_key) const
|
||||
{
|
||||
VarUsages usages;
|
||||
|
||||
vector<int> inOutTypes;
|
||||
bool isIntrinsic = isIntrinsicFunctionName(func_key.c_str());
|
||||
if (!isIntrinsic)
|
||||
{
|
||||
auto it = modified_pars.find(func_key);
|
||||
if (it != modified_pars.end())
|
||||
inOutTypes = it->second;
|
||||
}
|
||||
else if (isMpiFunction(func_key.c_str()))
|
||||
{
|
||||
if (func_key == "mpi_abort")
|
||||
inOutTypes = { IN_BIT, IN_BIT, OUT_BIT };
|
||||
if (func_key == "mpi_send")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
if (func_key == "mpi_isend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_recv")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_irecv")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_alltoall")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_alltoallv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_allgather")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_allgatherv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_allreduce")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_reduce")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_reduce_scatter")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_scatter")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_scatterv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_gather")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_gatherv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_sendrecv")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_sendrecv_replace")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_scan")
|
||||
inOutTypes = { IN_BIT, IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT | OUT_BIT };
|
||||
else if (func_key == "mpi_bcast")
|
||||
inOutTypes = { IN_BIT | OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_bsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
|
||||
else if (func_key == "mpi_bsend_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_ibsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_irsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_issend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_recv_init")
|
||||
inOutTypes = { OUT_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_rsend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
|
||||
else if (func_key == "mpi_rsend_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_send_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
else if (func_key == "mpi_ssend")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT };
|
||||
else if (func_key == "mpi_ssend_init")
|
||||
inOutTypes = { IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, IN_BIT, OUT_BIT };
|
||||
}
|
||||
|
||||
int param_no = 0;
|
||||
while (params_tree)
|
||||
{
|
||||
SgExpression* param = params_tree->lhs();
|
||||
|
||||
if (param->variant() == VAR_REF || isArrayRef(param))
|
||||
{
|
||||
if (inOutTypes.size())
|
||||
{
|
||||
if (param_no >= inOutTypes.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (FuncParam::isArgIn((int64_t)inOutTypes[param_no]))
|
||||
usages.insert_read(param);
|
||||
if (FuncParam::isArgOut((int64_t)inOutTypes[param_no]))
|
||||
usages.insert_write(param);
|
||||
}
|
||||
else
|
||||
{
|
||||
usages.insert_read(param);
|
||||
if (!isIntrinsic)
|
||||
usages.insert_write(param);
|
||||
}
|
||||
|
||||
findReadUsagesInExpression(param->lhs(), usages);
|
||||
findReadUsagesInExpression(param->rhs(), usages);
|
||||
}
|
||||
|
||||
param_no++;
|
||||
params_tree = params_tree->rhs();
|
||||
}
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::get_usages(SgStatement* st)
|
||||
{
|
||||
if (initialized.find(st->fileName()) == initialized.end())
|
||||
init(st->getFile());
|
||||
|
||||
VarUsages usages;
|
||||
// if statement is compound
|
||||
if (compound_statements.find(st->variant()) != compound_statements.end())
|
||||
usages = gatherUsagesForCompound(st);
|
||||
else
|
||||
{
|
||||
auto it = usages_by_statement.find(st);
|
||||
if (it == usages_by_statement.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
usages = it->second;
|
||||
}
|
||||
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::get_usages(vector<SgStatement*> &statements)
|
||||
{
|
||||
auto usages = VarUsages();
|
||||
|
||||
for (auto& st : statements)
|
||||
{
|
||||
auto st_usages = get_usages(st);
|
||||
usages.extend(st_usages);
|
||||
}
|
||||
return usages;
|
||||
}
|
||||
|
||||
VarUsages ReadWriteAnalyzer::gatherUsagesForCompound(SgStatement* compoundStatement) const
|
||||
{
|
||||
VarUsages all_usages;
|
||||
|
||||
SgStatement* last = compoundStatement->lastNodeOfStmt();
|
||||
SgStatement* runner = compoundStatement;
|
||||
while (runner != last)
|
||||
{
|
||||
if (runner->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (!isSgExecutableStatement(runner) || isDVM_stat(runner) || isSPF_stat(runner))
|
||||
{
|
||||
runner = runner->lexNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
all_usages.extend(findUsagesInStatement(runner));
|
||||
runner = runner->lexNext();
|
||||
}
|
||||
return all_usages;
|
||||
}
|
||||
|
||||
void ReadWriteAnalyzer::print() const
|
||||
{
|
||||
auto save = current_file->filename();
|
||||
|
||||
for (int i = 0; i < CurrentProject->numberOfFiles(); i++)
|
||||
{
|
||||
printf("file: %s\n", CurrentProject->file(i).filename());
|
||||
for (int j = 0; j < CurrentProject->file(i).numberOfFunctions(); j++)
|
||||
{
|
||||
printf("function: %s\n", CurrentProject->file(i).functions(j)->symbol()->identifier());
|
||||
SgStatement* runner = CurrentProject->file(i).functions(j);
|
||||
auto last = runner->lastNodeOfStmt();
|
||||
|
||||
while (runner != last)
|
||||
{
|
||||
if (runner->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
auto it = usages_by_statement.find(runner);
|
||||
if (it != usages_by_statement.end())
|
||||
{
|
||||
runner->unparsestdout();
|
||||
it->second.print();
|
||||
}
|
||||
runner = runner->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SgFile::switchToFile(save) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
map<string, vector<int>> ReadWriteAnalyzer::load_modified_pars(const map<string, vector<FuncInfo*>> &files)
|
||||
{
|
||||
map<string, vector<int>> res;
|
||||
|
||||
for (auto& funcs : files)
|
||||
{
|
||||
string file_name = funcs.first;
|
||||
|
||||
for (auto& func : funcs.second)
|
||||
{
|
||||
string func_key = func->funcName;
|
||||
res[func_key] = func->funcParams.inout_types;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user