finalyze moving
This commit is contained in:
38
src/DvmhRegions/DvmhRegion.cpp
Normal file
38
src/DvmhRegions/DvmhRegion.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "leak_detector.h"
|
||||
#include "DvmhRegion.h"
|
||||
|
||||
DvmhRegion::DvmhRegion(LoopGraph *loopNode, const std::string &fun_name) : fun_name(fun_name)
|
||||
{
|
||||
loops.push_back(loopNode);
|
||||
}
|
||||
|
||||
SgStatement* DvmhRegion::getFirstSt() const
|
||||
{
|
||||
if (loops.size() < 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return loops.front()->loop->GetOriginal();
|
||||
}
|
||||
|
||||
SgStatement* DvmhRegion::getLastSt() const
|
||||
{
|
||||
if (loops.size() < 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return loops.back()->loop->GetOriginal()->lastNodeOfStmt();
|
||||
}
|
||||
|
||||
void DvmhRegion::append(DvmhRegion& region)
|
||||
{
|
||||
for (auto& loop : region.getLoops())
|
||||
addLoop(loop);
|
||||
}
|
||||
|
||||
int DvmhRegion::getLineForSort() const
|
||||
{
|
||||
if (loops.size() == 0)
|
||||
return -1;
|
||||
|
||||
int line = loops[0]->lineNum;
|
||||
if (line < 0)
|
||||
line = loops[0]->altLineNum;
|
||||
return line;
|
||||
}
|
||||
28
src/DvmhRegions/DvmhRegion.h
Normal file
28
src/DvmhRegions/DvmhRegion.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class DvmhRegion
|
||||
{
|
||||
private:
|
||||
std::vector<LoopGraph*> loops;
|
||||
std::string fun_name;
|
||||
|
||||
public:
|
||||
DvmhRegion() { }
|
||||
DvmhRegion(LoopGraph *loopNode, const std::string &fun_name);
|
||||
|
||||
SgStatement* getFirstSt() const;
|
||||
SgStatement* getLastSt() const;
|
||||
|
||||
void addLoop(LoopGraph* newLoop) { loops.push_back(newLoop); }
|
||||
const std::string& getFunName() const { return fun_name; }
|
||||
void setFunName(const std::string& newName) { fun_name = newName; }
|
||||
const std::vector<LoopGraph*>& getLoops() const { return loops; }
|
||||
std::string getFileName() const { return getFirstSt()->fileName(); }
|
||||
void append(DvmhRegion& region);
|
||||
int getLineForSort() const;
|
||||
};
|
||||
|
||||
1598
src/DvmhRegions/DvmhRegionInserter.cpp
Normal file
1598
src/DvmhRegions/DvmhRegionInserter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
src/DvmhRegions/DvmhRegionInserter.h
Normal file
120
src/DvmhRegions/DvmhRegionInserter.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
#include "../ExpressionTransform/expr_transform.h"
|
||||
#include "../ParallelizationRegions/ParRegions.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "ReadWriteAnalyzer.h"
|
||||
#include "DvmhRegion.h"
|
||||
|
||||
|
||||
typedef std::set<DIST::Array* > ArraySet;
|
||||
struct ReadWrite
|
||||
{
|
||||
ArraySet read;
|
||||
ArraySet write;
|
||||
};
|
||||
typedef std::map<int, ReadWrite> UsageByLine;
|
||||
typedef std::map<std::string, UsageByLine> UsageByFile;
|
||||
|
||||
|
||||
class DvmhRegionInserter
|
||||
{
|
||||
// input data
|
||||
SgFile *file;
|
||||
std::map<int, LoopGraph*> loopGraphMap;
|
||||
const std::vector<LoopGraph*> loopGraph;
|
||||
const std::map<std::string, FuncInfo*> allFunctions;
|
||||
const std::vector<FuncInfo*> funcsForFile;
|
||||
bool isMpiProgram;
|
||||
|
||||
ReadWriteAnalyzer& rw_analyzer;
|
||||
std::map<FuncInfo*, std::set<LoopGraph*>> parallel_functions;
|
||||
std::set<DIST::Array*> writesToArraysInParallelLoops;
|
||||
std::set<DIST::Array*> usedArraysInParallelLoops;
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls;
|
||||
// operating data
|
||||
std::vector<DvmhRegion*> regions;
|
||||
|
||||
// region directives
|
||||
void findEdgesForRegions(const std::vector<LoopGraph*>&);
|
||||
bool hasLimitsToDvmhParallel(const LoopGraph*) const;
|
||||
void insertRegionDirectives();
|
||||
|
||||
// actual directives
|
||||
ArraySet symbs_to_arrs(std::set<SgSymbol*>) const;
|
||||
ArraySet get_used_arrs(SgStatement* st, int usage_type) const;
|
||||
ArraySet get_used_arrs_for_block(SgStatement* st, int usage_type) const;
|
||||
SgStatement* processSt(SgStatement *st, const std::vector<ParallelRegion*>* regs);
|
||||
|
||||
void insertActualDirective(SgStatement*, const ArraySet&, int, bool, const std::set<std::string>* = NULL);
|
||||
|
||||
void parFuncsInNode(LoopGraph *loop, bool isParallel);
|
||||
bool isLoopParallel(const LoopGraph *loop) const;
|
||||
std::vector<SgExpression*> getArrayList(Statement* start, Statement* end, bool left = false) const;
|
||||
ArraySet applyUseFilter(const ArraySet& block, const std::set<DIST::Array*>& filter) const;
|
||||
ArraySet excludePrivates(const ArraySet& block) const;
|
||||
ArraySet excludeRemotes(const ArraySet& block, SgStatement* remoteDir) const;
|
||||
void insertForProcCall(SgStatement* st, bool& skipGetActualIfProcCall, bool& skipActualIfProcCall);
|
||||
public:
|
||||
explicit DvmhRegionInserter(
|
||||
SgFile* curFile,
|
||||
const std::vector<LoopGraph*>& curLoopGraph,
|
||||
ReadWriteAnalyzer& rws,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls,
|
||||
const std::map<std::string, FuncInfo*>& allFunctions,
|
||||
const std::vector<FuncInfo*>& funcsForFile,
|
||||
bool mpi_program
|
||||
) : file(curFile), loopGraph(curLoopGraph), rw_analyzer(rws), arrayLinksByFuncCalls(arrayLinksByFuncCalls), allFunctions(allFunctions), funcsForFile(funcsForFile), isMpiProgram(mpi_program)
|
||||
{
|
||||
if (loopGraph.size())
|
||||
createMapLoopGraph(loopGraph, loopGraphMap);
|
||||
}
|
||||
|
||||
void insertDirectives(const std::vector<ParallelRegion*>* regs = NULL);
|
||||
void insertActualDirectives(const std::vector<ParallelRegion*>* regs);
|
||||
|
||||
void updateParallelFunctions(const std::map<std::string, std::vector<LoopGraph*>>& loopGraphs);
|
||||
void createInterfaceBlockForParallelFunctions(bool onlyRoutine = true);
|
||||
void removePrivatesFromParallelLoops();
|
||||
void addPrivatesToParallelLoops();
|
||||
void addUsedArrays(std::set<DIST::Array*>& arrays);
|
||||
void addUsedWriteArrays(std::set<DIST::Array*>& arrays);
|
||||
|
||||
void updateUsedArrays(const std::set<DIST::Array*>& used, const std::set<DIST::Array*>& usedForWrite)
|
||||
{
|
||||
ArraySet newSet = usedForWrite;
|
||||
for (auto& elem : usedForWrite)
|
||||
getRealArrayRefs(elem, elem, newSet, arrayLinksByFuncCalls);
|
||||
writesToArraysInParallelLoops = newSet;
|
||||
|
||||
newSet = used;
|
||||
for (auto& elem : used)
|
||||
getRealArrayRefs(elem, elem, newSet, arrayLinksByFuncCalls);
|
||||
usedArraysInParallelLoops = newSet;
|
||||
}
|
||||
|
||||
const std::set<FuncInfo*> getParallelFunctions() const {
|
||||
std::set<FuncInfo*> retVal;
|
||||
for (auto& elem : parallel_functions)
|
||||
retVal.insert(elem.first);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static void createInterfaceBlockForOutCall(FuncInfo* func, FuncInfo* callFrom);
|
||||
static void createInterfaceBlockForOutCalls(FuncInfo* func);
|
||||
|
||||
~DvmhRegionInserter()
|
||||
{
|
||||
for (auto& reg : regions)
|
||||
delete reg;
|
||||
}
|
||||
};
|
||||
|
||||
int insertDvmhRegions(SgProject& project, int files, const std::vector<ParallelRegion*>& parallelRegions,
|
||||
std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
|
||||
std::map<std::string, std::vector<LoopGraph*>> loopGraph,
|
||||
ReadWriteAnalyzer& rw_analyzer,
|
||||
std::map<std::string, std::vector<Messages>>& SPF_messages,
|
||||
const std::map<DIST::Array*, std::set<DIST::Array*>> arrayLinksByFuncCalls);
|
||||
72
src/DvmhRegions/LoopChecker.cpp
Normal file
72
src/DvmhRegions/LoopChecker.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "leak_detector.h"
|
||||
#include "LoopChecker.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void LoopChecker::updateLoopGraph(const map<string, FuncInfo*> &allFuncs)
|
||||
{
|
||||
for (auto &loopNode : loopGraph)
|
||||
updateLoopNode(loopNode, allFuncs);
|
||||
}
|
||||
|
||||
LoopCheckResults LoopChecker::updateLoopNode(LoopGraph *loop, const map<string, FuncInfo*> &allFuncs)
|
||||
{
|
||||
LoopCheckResults loopChecks = checkLoopForPurenessAndIO(loop, allFuncs);
|
||||
bool hasImpureCalls = loopChecks.hasImpureCalls;
|
||||
bool usesIO = loopChecks.usesIO;
|
||||
|
||||
if (loopChecks.linesOfIO.size() && usesIO)
|
||||
for (auto& elem : loopChecks.linesOfIO)
|
||||
loop->linesOfIO.insert(elem);
|
||||
|
||||
for (auto &nestedLoop : loop->children)
|
||||
{
|
||||
loopChecks = updateLoopNode(nestedLoop, allFuncs);
|
||||
hasImpureCalls |= loopChecks.hasImpureCalls;
|
||||
usesIO |= loopChecks.usesIO;
|
||||
}
|
||||
|
||||
loop->hasNonPureProcedures |= hasImpureCalls;
|
||||
loop->hasPrints |= usesIO;
|
||||
|
||||
return LoopCheckResults(loop->hasPrints, loop->hasNonPureProcedures);
|
||||
}
|
||||
|
||||
|
||||
// checks loop node itself, doesn't check its children
|
||||
LoopCheckResults LoopChecker::checkLoopForPurenessAndIO(const LoopGraph *loopNode, const map<string, FuncInfo*> &allFuncs) const
|
||||
{
|
||||
LoopCheckResults loopCheckResults;
|
||||
|
||||
for (auto &nameAndLineOfFuncCalled : loopNode->calls)
|
||||
{
|
||||
FuncInfo *calledFuncInfo = NULL;
|
||||
|
||||
auto it = allFuncs.find(nameAndLineOfFuncCalled.first);
|
||||
if (it != allFuncs.end())
|
||||
calledFuncInfo = it->second;
|
||||
|
||||
if (!calledFuncInfo)
|
||||
{
|
||||
if (isIntrinsicFunctionName(nameAndLineOfFuncCalled.first.c_str()))
|
||||
continue;
|
||||
else
|
||||
{ // if funcInfo was not found assume func to be impure
|
||||
loopCheckResults.hasImpureCalls = true;
|
||||
loopCheckResults.usesIO = true;
|
||||
loopCheckResults.linesOfIO.push_back(nameAndLineOfFuncCalled.second);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!calledFuncInfo->isPure)
|
||||
loopCheckResults.hasImpureCalls = true;
|
||||
|
||||
if (calledFuncInfo->usesIO())
|
||||
{
|
||||
loopCheckResults.usesIO = true;
|
||||
loopCheckResults.linesOfIO.push_back(nameAndLineOfFuncCalled.second);
|
||||
}
|
||||
}
|
||||
return loopCheckResults;
|
||||
}
|
||||
30
src/DvmhRegions/LoopChecker.h
Normal file
30
src/DvmhRegions/LoopChecker.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
struct LoopCheckResults
|
||||
{
|
||||
bool usesIO;
|
||||
bool hasImpureCalls;
|
||||
|
||||
std::vector<int> linesOfIO;
|
||||
|
||||
LoopCheckResults() : usesIO(false), hasImpureCalls(false) { }
|
||||
LoopCheckResults(bool io, bool calls) : usesIO(io), hasImpureCalls(calls) { }
|
||||
};
|
||||
|
||||
class LoopChecker
|
||||
{
|
||||
std::vector<LoopGraph*> &loopGraph;
|
||||
|
||||
LoopCheckResults checkLoopForPurenessAndIO(const LoopGraph *loopNode, const std::map<std::string, FuncInfo*> &allFuncs) const;
|
||||
LoopCheckResults updateLoopNode(LoopGraph *loop, const std::map<std::string, FuncInfo*> &allFuncs);
|
||||
public:
|
||||
explicit LoopChecker(std::vector<LoopGraph*> &graph) : loopGraph(graph) { }
|
||||
void updateLoopGraph(const std::map<std::string, FuncInfo*> &allFuncs);
|
||||
};
|
||||
341
src/DvmhRegions/ReadWriteAnalyzer.cpp
Normal file
341
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;
|
||||
}
|
||||
44
src/DvmhRegions/ReadWriteAnalyzer.h
Normal file
44
src/DvmhRegions/ReadWriteAnalyzer.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "VarUsages.h"
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
|
||||
|
||||
class ReadWriteAnalyzer
|
||||
{
|
||||
std::map<std::string, std::vector<FuncInfo*>> &funcInfo; // TODO: could be not initilized; should be rebuilt on invalidate()
|
||||
std::map<std::string, std::vector<int>> modified_pars; // func -> used for [in, inout, out] params,
|
||||
std::map<SgStatement*, VarUsages> usages_by_statement; // maps statements to variables used in them
|
||||
|
||||
std::set<std::string> initialized; // files was inited
|
||||
void init(SgFile*);
|
||||
|
||||
VarUsages findUsagesInStatement(SgStatement* st) const;
|
||||
VarUsages findUsagesInAssignment(SgStatement* st) const;
|
||||
void findReadUsagesInExpression(SgExpression* ex, VarUsages& toExtend) const;
|
||||
|
||||
const std::set<int> compound_statements = { FOR_NODE, LOOP_NODE, FUNC_HEDR, PROC_HEDR };
|
||||
VarUsages gatherUsagesForCompound(SgStatement* st) const;
|
||||
public:
|
||||
explicit ReadWriteAnalyzer(std::map<std::string, std::vector<FuncInfo*>> &funcInfo) : funcInfo(funcInfo)
|
||||
{ }
|
||||
|
||||
void invalidate(const std::string& fileName) { initialized.erase(fileName); }
|
||||
|
||||
VarUsages get_usages(SgStatement*);
|
||||
VarUsages get_usages(std::vector<SgStatement*>&);
|
||||
|
||||
VarUsages findUsagesInExpr(SgExpression* exp) const;
|
||||
VarUsages findUsagesInFuncCall(SgExpression*, const std::string&) const;
|
||||
|
||||
void print() const;
|
||||
|
||||
static std::map<std::string, std::vector<int>> load_modified_pars(const std::map<std::string, std::vector<FuncInfo*>>&);
|
||||
};
|
||||
195
src/DvmhRegions/RegionsMerger.cpp
Normal file
195
src/DvmhRegions/RegionsMerger.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include "leak_detector.h"
|
||||
#include "RegionsMerger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool RegionsMerger::compareByStart(const DvmhRegion *a, const DvmhRegion *b)
|
||||
{
|
||||
if (a->getLoops().size() < 1 || b->getLoops().size() < 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
int lineLeft = a->getLoops()[0]->lineNum;
|
||||
if (lineLeft < 0)
|
||||
lineLeft = a->getLoops()[0]->altLineNum;
|
||||
|
||||
int lineRight = b->getLoops()[0]->lineNum;
|
||||
if (lineRight < 0)
|
||||
lineRight = b->getLoops()[0]->altLineNum;
|
||||
return lineLeft < lineRight;
|
||||
}
|
||||
|
||||
bool RegionsMerger::canBeMoved(SgStatement* st, const DvmhRegion *region) const
|
||||
{
|
||||
// For now: st [a, d = b + c] can be moved IF [b, c] are not modified in region AND [a, d] not used for read in region
|
||||
// get usages for statement
|
||||
VarUsages st_usages = rw_analyzer.get_usages(st);
|
||||
|
||||
// get usages for region
|
||||
auto loop_statements = vector<SgStatement*>();
|
||||
for (auto& loop : region->getLoops())
|
||||
loop_statements.push_back(loop->loop);
|
||||
|
||||
auto region_usages = rw_analyzer.get_usages(loop_statements);
|
||||
|
||||
// analyze if statement can be placed before region
|
||||
if (sets_intersect(st_usages.get_reads(), region_usages.get_writes())) // check that [b, c] not modified in region
|
||||
return false;
|
||||
|
||||
if (sets_intersect(st_usages.get_writes(), region_usages.get_reads())) // check that [a, d] not read in region
|
||||
return false;
|
||||
|
||||
return true; // everything's ok
|
||||
}
|
||||
|
||||
vector<SgStatement*> RegionsMerger::getStatementsToMove(const DvmhRegion *first, const DvmhRegion *second, bool &can) const
|
||||
{
|
||||
// can not, abort operation
|
||||
if (first->getFileName() != second->getFileName() || first->getFunName() != second->getFunName())
|
||||
{
|
||||
can = false;
|
||||
return vector<SgStatement*>();
|
||||
}
|
||||
|
||||
vector<SgStatement*> toMove;
|
||||
SgStatement* mediumSt = first->getLastSt()->lexNext();
|
||||
|
||||
// skip DVM PARALLEL and hidden stats
|
||||
while (mediumSt->variant() == DVM_PARALLEL_ON_DIR || mediumSt->variant() < 0)
|
||||
mediumSt = mediumSt->lexNext();
|
||||
|
||||
//no statements between regions, so can
|
||||
if (mediumSt == second->getFirstSt() && mediumSt->variant() == FOR_NODE)
|
||||
{
|
||||
can = true;
|
||||
return vector<SgStatement*>();
|
||||
} //TODO
|
||||
else
|
||||
{
|
||||
can = false;
|
||||
return vector<SgStatement*>();
|
||||
}
|
||||
|
||||
//TODO: need to check and correct
|
||||
while (mediumSt->id() != second->getFirstSt()->id())
|
||||
{
|
||||
if (mediumSt->variant() == DVM_PARALLEL_ON_DIR)
|
||||
{
|
||||
mediumSt = mediumSt->lexNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (canBeMoved(mediumSt, first))
|
||||
toMove.push_back(mediumSt);
|
||||
else // can not, abort operation
|
||||
{
|
||||
can = false;
|
||||
return vector<SgStatement*>();
|
||||
}
|
||||
mediumSt = mediumSt->lexNext();
|
||||
}
|
||||
|
||||
return toMove;
|
||||
}
|
||||
|
||||
// Places statements before region
|
||||
void RegionsMerger::moveStatements(const vector<SgStatement*>& sts, const DvmhRegion* region)
|
||||
{
|
||||
SgStatement* prev = region->getFirstSt()->lexPrev();
|
||||
while (isDVM_stat(prev))
|
||||
prev = prev->lexPrev();
|
||||
|
||||
for (auto& st : sts)
|
||||
{
|
||||
SgStatement *toInsert = st->copyPtr();
|
||||
prev->insertStmtAfter(*toInsert, *prev->controlParent());
|
||||
prev = toInsert;
|
||||
st->deleteStmt();
|
||||
}
|
||||
|
||||
rw_analyzer.invalidate(region->getFileName());
|
||||
}
|
||||
|
||||
vector<DvmhRegion*> RegionsMerger::mergeRegions()
|
||||
{
|
||||
if (regions.size() < 2)
|
||||
return regions;
|
||||
|
||||
map<string, map<int, DvmhRegion*>> byFunc;
|
||||
for (auto& elem : regions)
|
||||
{
|
||||
const int line = elem->getLineForSort();
|
||||
const string fName = elem->getFunName();
|
||||
auto& itF = byFunc[fName];
|
||||
if (itF.find(line) != itF.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
itF[line] = elem;
|
||||
}
|
||||
|
||||
vector<DvmhRegion*> newRegions;
|
||||
|
||||
for (auto& regsForFunc : byFunc)
|
||||
{
|
||||
map<int, DvmhRegion*>& regionsByFunc = regsForFunc.second;
|
||||
|
||||
if (regionsByFunc.size() == 0)
|
||||
continue;
|
||||
|
||||
DvmhRegion* newRegion = new DvmhRegion();
|
||||
DvmhRegion* regionPrev = regionsByFunc.begin()->second;
|
||||
|
||||
bool isFirst = true;
|
||||
for (auto& loop : regionPrev->getLoops())
|
||||
newRegion->addLoop(loop);
|
||||
|
||||
for (auto& region : regionsByFunc)
|
||||
{
|
||||
if (newRegion->getFunName() == "" && region.second->getLoops().size() > 0)
|
||||
{
|
||||
SgStatement* func_st = getFuncStat(region.second->getLoops()[0]->loop);
|
||||
string fun_name = func_st->symbol()->identifier();
|
||||
newRegion->setFunName(fun_name);
|
||||
}
|
||||
|
||||
if (isFirst) // skip first region
|
||||
{
|
||||
isFirst = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool can = true;
|
||||
auto toMove = getStatementsToMove(regionPrev, region.second, can);
|
||||
if (can)
|
||||
{
|
||||
//TODO
|
||||
if (toMove.size())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
// moveStatements(toMove, regionPrev);
|
||||
}
|
||||
else
|
||||
{
|
||||
__spf_print(1, " region before loop on line %d (alt %d) cannot be merged\n",
|
||||
region.second->getLoops()[0]->lineNum, region.second->getLoops()[0]->altLineNum);
|
||||
toMove = getStatementsToMove(regionPrev, region.second, can);
|
||||
newRegions.push_back(newRegion);
|
||||
newRegion = new DvmhRegion();
|
||||
}
|
||||
|
||||
newRegion->append(*region.second);
|
||||
regionPrev = region.second;
|
||||
}
|
||||
newRegions.push_back(newRegion);
|
||||
}
|
||||
|
||||
for (auto& old : regions)
|
||||
delete old;
|
||||
regions.clear();
|
||||
return newRegions;
|
||||
}
|
||||
|
||||
bool RegionsMerger::sets_intersect(const set<SgSymbol*>& set1, const set<SgSymbol*>& set2) const
|
||||
{
|
||||
for (auto& symb : set1)
|
||||
if (set2.find(symb) != set2.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
19
src/DvmhRegions/RegionsMerger.h
Normal file
19
src/DvmhRegions/RegionsMerger.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "DvmhRegions/DvmhRegionInserter.h"
|
||||
|
||||
class RegionsMerger
|
||||
{
|
||||
std::vector<DvmhRegion*> ®ions;
|
||||
ReadWriteAnalyzer &rw_analyzer;
|
||||
|
||||
bool canBeMoved(SgStatement* st, const DvmhRegion *region) const;
|
||||
std::vector<SgStatement*> getStatementsToMove(const DvmhRegion *first, const DvmhRegion *second, bool&) const;
|
||||
void moveStatements(const std::vector<SgStatement*>& sts, const DvmhRegion* region);
|
||||
bool sets_intersect(const std::set<SgSymbol*>&, const std::set<SgSymbol*>&) const;
|
||||
|
||||
static bool compareByStart(const DvmhRegion* a, const DvmhRegion* b);
|
||||
public:
|
||||
explicit RegionsMerger(std::vector<DvmhRegion*>& old_regions, ReadWriteAnalyzer& rw) : regions(old_regions), rw_analyzer(rw) { }
|
||||
std::vector<DvmhRegion*> mergeRegions();
|
||||
};
|
||||
36
src/DvmhRegions/TypedSymbol.cpp
Normal file
36
src/DvmhRegions/TypedSymbol.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "leak_detector.h"
|
||||
#include "TypedSymbol.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TypedSymbol::TypedSymbol(SgExpression* orig_exp)
|
||||
{
|
||||
if (orig_exp->variant() == VAR_REF || orig_exp->variant() == ARRAY_REF)
|
||||
orig = OriginalSymbol(orig_exp->symbol());
|
||||
|
||||
type = VAR_TYPE::VAR_UNDEFINED;
|
||||
|
||||
if (orig_exp->variant() == VAR_REF)
|
||||
type = VAR_TYPE::VAR_SCALAR;
|
||||
|
||||
if (orig_exp->variant() == ARRAY_REF)
|
||||
{
|
||||
type = VAR_TYPE::VAR_ARR;
|
||||
DIST::Array* arr = getArrayFromDeclarated(declaratedInStmt(orig), orig->identifier());
|
||||
if (arr == NULL) //for strings charecter(*)
|
||||
type = VAR_TYPE::VAR_SCALAR;
|
||||
else if (!arr->IsNotDistribute())
|
||||
type = VAR_TYPE::VAR_DISTR_ARR;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator== (const TypedSymbol& lhs, const TypedSymbol& rhs)
|
||||
{
|
||||
return string(OriginalSymbol(lhs.orig)->identifier()) == string(OriginalSymbol(rhs.orig)->identifier()) &&
|
||||
OriginalSymbol(lhs.orig)->scope()->id() == OriginalSymbol(rhs.orig)->scope()->id();
|
||||
}
|
||||
|
||||
bool operator< (const TypedSymbol& lhs, const TypedSymbol& rhs)
|
||||
{
|
||||
return OriginalSymbol(lhs.orig)->id() < OriginalSymbol(rhs.orig)->id();
|
||||
}
|
||||
18
src/DvmhRegions/TypedSymbol.h
Normal file
18
src/DvmhRegions/TypedSymbol.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvm.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include <string>
|
||||
|
||||
enum class VAR_TYPE { VAR_ARR, VAR_DISTR_ARR, VAR_SCALAR, VAR_ANY, VAR_UNDEFINED };
|
||||
|
||||
class TypedSymbol
|
||||
{
|
||||
public:
|
||||
SgSymbol* orig;
|
||||
VAR_TYPE type;
|
||||
|
||||
TypedSymbol(SgExpression*);
|
||||
friend bool operator== (const TypedSymbol& lhs, const TypedSymbol& rhs);
|
||||
friend bool operator< (const TypedSymbol& lhs, const TypedSymbol& rhs);
|
||||
};
|
||||
97
src/DvmhRegions/VarUsages.cpp
Normal file
97
src/DvmhRegions/VarUsages.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "leak_detector.h"
|
||||
#include "VarUsages.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void VarUsages::extend(const VarUsages& to_insert)
|
||||
{
|
||||
undefined |= to_insert.undefined;
|
||||
|
||||
reads.insert(to_insert.reads.begin(), to_insert.reads.end());
|
||||
writes.insert(to_insert.writes.begin(), to_insert.writes.end());
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_reads(const set<VAR_TYPE> var_type) const
|
||||
{
|
||||
if (undefined)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
return filter(reads, var_type);
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_writes(const set<VAR_TYPE> var_type) const
|
||||
{
|
||||
if (undefined)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
return filter(writes, var_type);
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_all(const set<VAR_TYPE> var_type) const
|
||||
{
|
||||
set<TypedSymbol> all_usages;
|
||||
all_usages.insert(reads.begin(), reads.end());
|
||||
all_usages.insert(writes.begin(), writes.end());
|
||||
|
||||
return filter(all_usages, var_type);
|
||||
}
|
||||
|
||||
set<SgSymbol*> VarUsages::get_reads() const { return get_reads({ VAR_TYPE::VAR_ANY }); }
|
||||
set<SgSymbol*> VarUsages::get_writes() const { return get_writes({ VAR_TYPE::VAR_ANY }); }
|
||||
set<SgSymbol*> VarUsages::get_all() const { return get_all({ VAR_TYPE::VAR_ANY }); }
|
||||
|
||||
set<SgSymbol*> VarUsages::filter(const set<TypedSymbol> &symbols, const set<VAR_TYPE> var_type)
|
||||
{
|
||||
set<SgSymbol*> filtered;
|
||||
if (var_type.find(VAR_TYPE::VAR_ANY) != var_type.end())
|
||||
for (auto& s : symbols)
|
||||
filtered.insert(s.orig);
|
||||
else
|
||||
for (auto& s : symbols)
|
||||
if (var_type.find(s.type) != var_type.end())
|
||||
filtered.insert(s.orig);
|
||||
return filtered;
|
||||
}
|
||||
|
||||
void VarUsages::insert_undefined(const TypedSymbol& s)
|
||||
{
|
||||
undefined = true;
|
||||
|
||||
reads.insert(s);
|
||||
writes.insert(s);
|
||||
}
|
||||
|
||||
void VarUsages::insert_read(const TypedSymbol& s) { reads.insert(s); }
|
||||
void VarUsages::insert_write(const TypedSymbol& s) { writes.insert(s); }
|
||||
|
||||
void VarUsages::print() const
|
||||
{
|
||||
printf("reads: ");
|
||||
if (undefined)
|
||||
printf("not_defined");
|
||||
else
|
||||
{
|
||||
for (auto& s : reads)
|
||||
printf("%s ", s.orig->identifier());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("writes: ");
|
||||
if (undefined)
|
||||
printf("not_defined");
|
||||
else
|
||||
{
|
||||
for (auto& s : writes)
|
||||
printf("%s ", s.orig->identifier());
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("all: ");
|
||||
for (auto& s : get_all({ VAR_TYPE::VAR_ANY }))
|
||||
printf("%s ", s->identifier());
|
||||
printf("\n");
|
||||
|
||||
printf("***\n");
|
||||
}
|
||||
|
||||
bool VarUsages::is_undefined() const { return undefined; }
|
||||
33
src/DvmhRegions/VarUsages.h
Normal file
33
src/DvmhRegions/VarUsages.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "dvm.h"
|
||||
#include "TypedSymbol.h"
|
||||
#include <set>
|
||||
|
||||
|
||||
class VarUsages
|
||||
{
|
||||
std::set<TypedSymbol> reads;
|
||||
std::set<TypedSymbol> writes;
|
||||
bool undefined;
|
||||
|
||||
public:
|
||||
VarUsages() : undefined(false) { }
|
||||
void extend(const VarUsages&);
|
||||
|
||||
void insert_undefined(const TypedSymbol&);
|
||||
void insert_read(const TypedSymbol&);
|
||||
void insert_write(const TypedSymbol&);
|
||||
|
||||
bool is_undefined() const;
|
||||
std::set<SgSymbol*> get_reads(const std::set<VAR_TYPE>) const;
|
||||
std::set<SgSymbol*> get_writes(const std::set<VAR_TYPE>) const;
|
||||
std::set<SgSymbol*> get_all(const std::set<VAR_TYPE>) const;
|
||||
|
||||
std::set<SgSymbol*> get_reads() const;
|
||||
std::set<SgSymbol*> get_writes() const;
|
||||
std::set<SgSymbol*> get_all() const;
|
||||
|
||||
static std::set<SgSymbol*> filter(const std::set<TypedSymbol>&, const std::set<VAR_TYPE>);
|
||||
void print() const;
|
||||
};
|
||||
Reference in New Issue
Block a user