Files
SAPFOR/Sapfor/_src/DynamicAnalysis/createParallelRegions.cpp
2025-03-12 12:37:19 +03:00

358 lines
11 KiB
C++

#include "dvm.h"
#include <stdio.h>
#include <iostream>
#include "./createParallelRegions.h"
#include "../CreateInterTree/CreateInterTree.h"
#include "../GraphCall/graph_calls.h"
#include "./gcov_info.h"
#include "./gCov_parser_func.h"
#include "../Utils/leak_detector.h"
#include <map>
#include <vector>
#include <string>
#include <stack>
using std::vector;
using std::map;
using std::string;
using std::stack;
using std::pair;
using std::to_string;
static void markNestedIntervals(SpfInterval *interval)
{
for (auto &item : interval->nested)
{
item->isNested = true;
if (!item->begin->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (item->begin->symbol()->identifier() != NULL)
markNestedIntervals(item);
}
}
static int countOfIntervals(const SpfInterval *interval, const SpfInterval *mainInterval)
{
int count = 0;
for (auto &item : mainInterval->nested)
{
if (item == interval)
count++;
else
count += countOfIntervals(interval, item);
}
return count;
}
static void performFuncTime(const map<string, vector<FuncInfo*>> &funcInfo, map<string, int> &countFunc)
{
int count = 0;
for (auto &str : funcInfo)
{
count = 0;
for (auto *info : str.second)
{
count += (info->callsTo).size();
if (countFunc.find(info->funcName) != countFunc.end())
countFunc[info->funcName] += count;
else
countFunc.insert(make_pair(info->funcName, count));
}
}
}
double performTime(SgProject* project, SgStatement *src, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls, int recLevel)
{
SgStatement* stmt = src;
if (!src->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (!isSgExecutableStatement(stmt))
return 0.0;
auto gCovForFile = gCovInfo.find(string(stmt->fileName()));
if (gCovForFile == gCovInfo.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto gCovForStmt = gCovForFile->second.find(stmt->lineNumber());
if (gCovForStmt == gCovForFile->second.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const Gcov_info& info = gCovForStmt->second;
double count = 0.0;
switch (stmt->variant())
{
case PROC_STAT:
{
if (recLevel <= 5)
{
SgCallStmt *call = (SgCallStmt*)src;
if (info.getCountCalls() == 0)
break;
SgStatement *body = NULL;
string funcName(call->name()->identifier());
auto num = calls.find(funcName);
// its not a user function
if (num == calls.end())
break;
for (int j = 0; j < project->numberOfFiles(); ++j)
{
SgFile& file = project->file(j);
if (SgFile::switchToFile(file.filename()) == -1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < file.numberOfFunctions(); ++i)
{
if (!strcmp(file.functions(i)->symbol()->identifier(), funcName.c_str()))
{
body = file.functions(i);
break;
}
}
}
if (body == NULL)
break;
while (body && body->variant() != RETURN_STAT)
{
count += performTime(project, body, gCovInfo, calls, recLevel + 1);
if (!body->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
body = body->lexNext();
}
count /= num->second;
}
break;
}
case IF_NODE:
case LOGIF_NODE:
case ELSEIF_NODE:
{
SgIfStmt* ifSt = (SgIfStmt*)src;
SgStatement* tmp = ifSt->trueBody();
int t = 0;
while (tmp->variant() != CONTROL_END)
{
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
tmp = tmp->lexNext();
}
count += (info.getBranches()[0].getPercent()) * 0.01 * t;
t = 0;
tmp = ifSt->falseBody();
while (tmp && tmp->variant() != CONTROL_END)
{
t += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
tmp = tmp->lexNext();
}
count += (info.getBranches()[1].getPercent()) * 0.01 * t;
break;
}
case WHILE_NODE:
{
SgWhileStmt* whileSt = (SgWhileStmt*)src;
SgStatement* tmp = whileSt->body();
while (tmp->variant() != CONTROL_END)
{
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
if (!tmp->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
tmp = tmp->lexNext();
}
break;
}
case FOR_NODE:
{
SgForStmt* forSt = (SgForStmt*)src;
SgStatement* tmp = forSt->body();
while (tmp->variant() != CONTROL_END)
{
count += performTime(project, tmp, gCovInfo, calls, recLevel + 1);
if (!tmp->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
tmp = tmp->lexNext();
}
break;
}
case ADD_OP:
case MULT_OP:
case DIV_OP:
case SUB_OP:
case ASSGN_OP:
case ASSIGN_STAT:
// let frequency be about 2 GHerz
count += 0.0000000005 * info.getExecutedCount();
break;
case WRITE_STAT:
case READ_STAT:
// read/write operations are slower
count += 0.0000000015 * info.getExecutedCount();
break;
default:
break;
}
return count;
}
typedef pair<vector<SpfInterval*>, int> PositionInVector;
typedef stack<PositionInVector> IntervalStack;
double performIntervalTime(SgProject* project, const SpfInterval *interval, const map<string, map<int, Gcov_info>> &gCovInfo, map<string, int> &calls)
{
double time = 0.0;
for (SgStatement *stat = interval->begin; stat != interval->ends[interval->ends.size() - 1]; stat = stat->lexNext())
{
time += performTime(project, stat, gCovInfo, calls, 0);
if (!stat->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return time;
}
void createParallelRegions(SgProject* project, SpfInterval *mainInterval, const map<string, map<int, Gcov_info>> &gCovInfo, const map<string, vector<FuncInfo*>> &funcInfo)
{
double percent = 0.8;
vector<SpfRegion> regions;
map<string, int> calls;
performFuncTime(funcInfo, calls);
if (mainInterval == NULL)
{
__spf_print(1, "internal error in analysis, directives will not be generated for this file!\n");
return;
}
double sumTime = performIntervalTime(project, mainInterval, gCovInfo, calls);
double alreadyHavePercent = 0.0;
int id = 1;
int i = 0;
IntervalStack stack;
vector<SpfInterval*> iterated;
vector<SpfInterval*> nested;
iterated.push_back(mainInterval);
while (alreadyHavePercent <= percent)
{
if (i >= iterated.size())
{
if (!stack.empty())
{
iterated = stack.top().first;
i = stack.top().second;
stack.pop();
}
else
break;
}
SpfInterval* interval = iterated[i];
if (!interval || interval->isRegion || interval->isNested)
{
i++;
continue;
}
double time = performIntervalTime(project, interval, gCovInfo, calls);
int count = countOfIntervals(interval, mainInterval);
if (count != 0) time *= count;
double percentOfInterval = time / sumTime;
if (percentOfInterval + alreadyHavePercent <= percent)
{
__spf_print(1, "Add interval with %f percent, we have %f percent\n", percentOfInterval, percentOfInterval + alreadyHavePercent);
SpfRegion region(id, time, interval->begin, interval->ends[0]);
region.time = time;
region.id = id;
iterated[i]->isRegion = true;
markNestedIntervals(interval);
id++;
i++;
regions.push_back(region);
alreadyHavePercent += percentOfInterval;
}
else
{
__spf_print(1, "divide interval with %f percent\n", percentOfInterval);
if (i < iterated.size() - 1)
stack.push(make_pair(vector<SpfInterval*>(iterated.begin(), iterated.end()), i + 1));
iterated.clear();
iterated = vector<SpfInterval*>(interval->nested.begin(), interval->nested.end());
i = 0;
}
}
i = 0;
while (i < regions.size())
{
if (i > 0 && !regions[i-1].end->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (i > 0 && regions[i - 1].end->lexNext() == regions[i].start)
{
regions[i - 1].end = regions[i].end;
regions.erase(regions.begin() + i);
continue;
}
i++;
}
__spf_print(1, "Coverage of region is %f percent, count of regions is %d\n", alreadyHavePercent, regions.size());
for (auto &item : regions)
{
if (!item.start->switchToFile())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgStatement *startRegion = new SgStatement(SPF_PARALLEL_REG_DIR);
SgStatement *endRegion = new SgStatement(SPF_END_PARALLEL_REG_DIR);
startRegion->setSymbol(*(new SgSymbol(VARIABLE_NAME, to_string(item.id).c_str())));
SgStatement *st = item.start;
while (!isSgExecutableStatement(st))
st = st->lexNext();
startRegion->setFileId(st->getFileId());
startRegion->setProject(st->getProject());
startRegion->setlineNumber(st->lineNumber());
startRegion->setFileName(st->fileName());
st->insertStmtBefore(*startRegion, *st->controlParent());
SgStatement *next = item.end->lexNext();
startRegion->setFileId(next->getFileId());
startRegion->setProject(next->getProject());
startRegion->setlineNumber(next->lineNumber());
startRegion->setFileName(next->fileName());
next->insertStmtBefore(*endRegion, *next->controlParent());
}
}