moved
This commit is contained in:
882
Sapfor/_src/CreateInterTree/CreateInterTree.cpp
Normal file
882
Sapfor/_src/CreateInterTree/CreateInterTree.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
#include "CreateInterTree.h"
|
||||
#include "../Utils/SgUtils.h"
|
||||
#include "../Utils/utils.h"
|
||||
#include "../GraphCall/graph_calls_func.h"
|
||||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using std::vector;
|
||||
using std::list;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::set;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::fstream;
|
||||
|
||||
static long int getNextTag()
|
||||
{
|
||||
static long int INTERVAL_TAG = 0;
|
||||
return INTERVAL_TAG++;
|
||||
}
|
||||
|
||||
//Debug funcs
|
||||
static void printTree(SpfInterval* inter, fstream &file, int level)
|
||||
{
|
||||
if (!(inter->ifInclude))
|
||||
{
|
||||
for (int i = 0; i < inter->nested.size(); i++)
|
||||
printTree(inter->nested[i], file, level + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inter->begin->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
for (int i = 0; i < level; i++)
|
||||
file << " ";
|
||||
file << " Begin INTERVAL #" << inter->tag << " (var " << tag[inter->begin->variant()];
|
||||
if (inter->begin->variant() == PROC_HEDR || inter->begin->variant() == FUNC_HEDR)
|
||||
{
|
||||
string name(inter->begin->symbol()->identifier());
|
||||
convertToUpper(name);
|
||||
file << ", " << name;
|
||||
}
|
||||
file << ", gcov_calls " << inter->calls_count << ") ";
|
||||
file << " [" << inter->lineFile.first << ", " << inter->lineFile.second << "]";
|
||||
if (inter->parent == NULL && level != 0)
|
||||
file << " -- through PROC_CALL --";
|
||||
file << "\n";
|
||||
|
||||
for (int i = 0; i < inter->nested.size(); i++)
|
||||
printTree(inter->nested[i], file, level + 1);
|
||||
|
||||
for (int i = 0; i < inter->ends.size(); i++)
|
||||
{
|
||||
for (int i = 0; i < level; i++)
|
||||
file << " ";
|
||||
file << " End INTERVAL #" << inter->tag << " (exit lvl " << inter->exit_levels[i] << ", var " << tag[inter->ends[i]->variant()] << ") ";
|
||||
file << "line " << inter->ends[i]->lineNumber() << endl;
|
||||
}
|
||||
if (level == 0)
|
||||
file << endl;
|
||||
}
|
||||
|
||||
void saveIntervals(const string &fileName, map<string, vector<SpfInterval*>> &intervals)
|
||||
{
|
||||
fstream file_intervals;
|
||||
|
||||
file_intervals.open(fileName, fstream::out);
|
||||
for (auto &byfile : intervals)
|
||||
{
|
||||
file_intervals << "**** INTERVALS FOR FILE '" << byfile.first << "'\n";
|
||||
for (auto &interval : byfile.second)
|
||||
printTree(interval, file_intervals, 0);
|
||||
}
|
||||
file_intervals.close();
|
||||
}
|
||||
|
||||
//Labels funcs
|
||||
static void matchGotoLabels(SgStatement *st, map<int, vector<int>> &gotoStmts)
|
||||
{
|
||||
map<int, vector<int>> labelsRef;
|
||||
|
||||
findAllRefsToLables(st, labelsRef, false);
|
||||
|
||||
for (auto &key : labelsRef)
|
||||
for (auto &it : key.second)
|
||||
gotoStmts[it].push_back(key.first);
|
||||
}
|
||||
|
||||
static void findAllLabels(SgStatement* st, map<int, int> &labelsRef)
|
||||
{
|
||||
SgStatement* end = st->lastNodeOfStmt();
|
||||
|
||||
while (st != end)
|
||||
{
|
||||
if (st->hasLabel())
|
||||
labelsRef[st->label()->id()] = st->lineNumber();
|
||||
st = st->lexNext();
|
||||
}
|
||||
if (end->hasLabel())
|
||||
labelsRef[end->label()->id()] = end->lineNumber();
|
||||
}
|
||||
|
||||
//Nested intervals removal
|
||||
static int getNestedLevel(SgStatement* loop_stmt)
|
||||
{
|
||||
int depth = 0;
|
||||
SgStatement *current_loop = loop_stmt->lexNext();
|
||||
SgStatement* controlEnd = loop_stmt->lastNodeOfStmt()->lexPrev();
|
||||
SgStatement *controlEnd2 = current_loop->lastNodeOfStmt();
|
||||
|
||||
while (isSgForStmt(current_loop) && isSgControlEndStmt(controlEnd) && controlEnd == controlEnd2)
|
||||
{
|
||||
current_loop = current_loop->lexNext();
|
||||
controlEnd = controlEnd->lexPrev();
|
||||
controlEnd2 = current_loop->lastNodeOfStmt();
|
||||
depth++;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
static void removeNestedIntervals(SpfInterval* interval)
|
||||
{
|
||||
if (isSgForStmt(interval->begin))
|
||||
{
|
||||
int depth = getNestedLevel(interval->begin);
|
||||
SpfInterval *current_interval = interval;
|
||||
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
current_interval = current_interval->nested[0];
|
||||
current_interval->ifInclude = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &include : interval->nested)
|
||||
removeNestedIntervals(include);
|
||||
}
|
||||
|
||||
// Merge trees functions.
|
||||
static int compareIntervals(SpfInterval* interval1, SpfInterval* interval2)
|
||||
{
|
||||
SgStatement* begin_st_1 = interval1->begin;
|
||||
while (!isSgExecutableStatement(begin_st_1) || isSPF_stat(begin_st_1) || isDVM_stat(begin_st_1))
|
||||
begin_st_1 = begin_st_1->lexNext();
|
||||
|
||||
SgStatement* begin_st_2 = interval2->begin;
|
||||
while (!isSgExecutableStatement(begin_st_2) || isSPF_stat(begin_st_2) || isDVM_stat(begin_st_2))
|
||||
begin_st_2 = begin_st_2->lexNext();
|
||||
|
||||
int begin_1 = begin_st_1->lineNumber();
|
||||
int begin_2 = begin_st_2->lineNumber();
|
||||
int end_1 = interval1->ends[0]->lineNumber();
|
||||
int end_2 = interval2->ends[0]->lineNumber();
|
||||
|
||||
if((begin_1 == begin_2 && end_1 == end_2) || end_1 <= begin_2 || begin_1 >= end_2)
|
||||
return 0;
|
||||
|
||||
if(begin_1 <= begin_2 && end_1 >= end_2)
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void insertIntervalIntoTree(vector<SpfInterval*> &tree, SpfInterval* userInterval)
|
||||
{
|
||||
bool ifDeleteNested = false;
|
||||
|
||||
for(int i = 0; i < tree.size(); i++)
|
||||
{
|
||||
int compare_result = compareIntervals(tree[i], userInterval);
|
||||
|
||||
if(compare_result == 0)
|
||||
continue;
|
||||
|
||||
if(compare_result > 0)
|
||||
{
|
||||
int amount = 0;
|
||||
|
||||
for(int j = 1; j < tree[i]->ends.size(); j++)
|
||||
{
|
||||
int endLineNumber = tree[i]->ends[j]->lineNumber();
|
||||
|
||||
if(endLineNumber >= userInterval->begin->lineNumber() && endLineNumber <= userInterval->ends[0]->lineNumber())
|
||||
{
|
||||
userInterval->ends.push_back(tree[i]->ends[j]);
|
||||
userInterval->exit_levels.push_back(0);
|
||||
|
||||
tree[i]->ends[j] = NULL;
|
||||
amount++;
|
||||
}
|
||||
}
|
||||
|
||||
tree[i]->ends.erase(std::remove_if(tree[i]->ends.begin(), tree[i]->ends.end(), [](SgStatement* stmt) {return (stmt == NULL);}), tree[i]->ends.end());
|
||||
for(int j = 0; j < amount; j++)
|
||||
tree[i]->exit_levels.pop_back();
|
||||
|
||||
insertIntervalIntoTree(tree[i]->nested, userInterval);
|
||||
return;
|
||||
}
|
||||
|
||||
userInterval->nested.push_back(tree[i]);
|
||||
userInterval->parent = tree[i]->parent;
|
||||
tree[i]->parent = userInterval;
|
||||
tree[i] = userInterval;
|
||||
|
||||
if(ifDeleteNested)
|
||||
tree[i] = NULL;
|
||||
else
|
||||
ifDeleteNested = true;
|
||||
}
|
||||
|
||||
tree.erase(std::remove_if(tree.begin(), tree.end(), [](SpfInterval* interval) {return (interval == NULL);}), tree.end());
|
||||
}
|
||||
|
||||
static void mergeTrees(vector<SpfInterval*> &fileIntervals, vector<SpfInterval*> &userIntervals)
|
||||
{
|
||||
for(auto &userInterval : userIntervals)
|
||||
insertIntervalIntoTree(fileIntervals, userInterval);
|
||||
}
|
||||
|
||||
// Calibrate interval exits.
|
||||
static void calibrateExits(const vector<SpfInterval*>& fileIntervals, const map<int, int> &labelsRef, map<int, vector<int>> &gotoStmts, int level)
|
||||
{
|
||||
for(auto &interval : fileIntervals)
|
||||
{
|
||||
for(int i = 1; i < interval->ends.size(); i++)
|
||||
{
|
||||
int variant = interval->ends[i]->variant();
|
||||
int &exit_level = interval->exit_levels[i];
|
||||
|
||||
if (variant == RETURN_STAT || variant == STOP_STAT || variant == EXIT_STMT)
|
||||
exit_level = level;
|
||||
|
||||
if (variant == EXIT_STMT)
|
||||
exit_level = 1;
|
||||
|
||||
for (auto&lab : gotoStmts[interval->ends[i]->lineNumber()])
|
||||
{
|
||||
auto itL = labelsRef.find(lab);
|
||||
if (itL == labelsRef.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const int label_line = itL->second;
|
||||
if (label_line == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
int depth = 0;
|
||||
|
||||
SpfInterval* searchInterval = interval;
|
||||
while (label_line < searchInterval->begin->lineNumber() || label_line > searchInterval->ends[0]->lineNumber())
|
||||
{
|
||||
searchInterval = searchInterval->parent;
|
||||
depth++;
|
||||
if (searchInterval == NULL)
|
||||
break;
|
||||
}
|
||||
exit_level = depth;
|
||||
}
|
||||
}
|
||||
|
||||
calibrateExits(interval->nested, labelsRef, gotoStmts, level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void removeUserIntervals(SgFile *file)
|
||||
{
|
||||
for (SgStatement* st = file->firstStatement(); st; st = st->lexNext())
|
||||
{
|
||||
const int var = st->variant();
|
||||
if (var == DVM_INTERVAL_DIR || var == DVM_EXIT_INTERVAL_DIR || var == DVM_ENDINTERVAL_DIR)
|
||||
{
|
||||
//move comment to next statement
|
||||
if (st->comments())
|
||||
{
|
||||
const char* comms = st->comments();
|
||||
string comments(comms);
|
||||
st->delComments();
|
||||
|
||||
SgStatement* next = st->lexNext();
|
||||
if (next)
|
||||
next->addComment(comments.c_str());
|
||||
}
|
||||
|
||||
st = st->lexPrev();
|
||||
st->lexNext()->deleteStmt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find intervals functions.
|
||||
static void findUserIntervals(SgStatement *startSt, vector<SpfInterval*> &userIntervals, vector<Messages> &messages)
|
||||
{
|
||||
SpfInterval *currentInterval = NULL;
|
||||
|
||||
SgStatement *endSt = startSt->lastNodeOfStmt();
|
||||
SgStatement *currentSt = startSt;
|
||||
|
||||
set<SpfInterval*> userIntervalsSet;
|
||||
|
||||
while (currentSt != endSt)
|
||||
{
|
||||
if(currentSt->variant() == DVM_INTERVAL_DIR)
|
||||
{
|
||||
SgStatement* begin = currentSt;
|
||||
while (isDVM_stat(begin))
|
||||
begin = begin->lexNext();
|
||||
|
||||
SpfInterval *inter = new SpfInterval(currentSt->lineNumber());
|
||||
inter->begin = begin;
|
||||
inter->lineFile = std::make_pair(begin->lineNumber(), begin->fileName());
|
||||
inter->parent = currentInterval;
|
||||
inter->tag = getNextTag();
|
||||
|
||||
userIntervals.push_back(inter);
|
||||
|
||||
currentInterval = inter;
|
||||
userIntervalsSet.insert(currentInterval);
|
||||
}
|
||||
|
||||
if(currentSt->variant() == DVM_ENDINTERVAL_DIR)
|
||||
{
|
||||
if (currentInterval == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
SgStatement* end = currentSt;
|
||||
while(isDVM_stat(end))
|
||||
end = end->lexPrev();
|
||||
|
||||
currentInterval->ends.push_back(end);
|
||||
currentInterval->exit_levels.push_back(0);
|
||||
|
||||
currentInterval = currentInterval->parent;
|
||||
}
|
||||
|
||||
currentSt = currentSt->lexNext();
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
//check for ends
|
||||
for (auto& inter : userIntervalsSet)
|
||||
{
|
||||
if (inter->begin == NULL)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (inter->ends.size() == 0)
|
||||
{
|
||||
wstring messageR, messageE;
|
||||
__spf_printToLongBuf(messageE, L"Can not find end of DVM's interval");
|
||||
__spf_printToLongBuf(messageR, R150);
|
||||
|
||||
messages.push_back(Messages(ERROR, inter->userIntervalLine, messageR, messageE, 1052));
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (error)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
static void findIntervals(SpfInterval *interval, map<int, int> &labelsRef, map<int, vector<int>> &gotoStmts, SgStatement *¤tSt)
|
||||
{
|
||||
int currentVar = -1;
|
||||
SgStatement* endStatement = interval->parent ? interval->ends[0] : interval->begin->lastNodeOfStmt();
|
||||
|
||||
while (currentSt != endStatement && currentVar != CONTAINS_STMT)
|
||||
{
|
||||
currentSt = currentSt->lexNext();
|
||||
currentVar = currentSt->variant();
|
||||
|
||||
if (currentSt->fileName() != string(interval->begin->fileName()))
|
||||
continue;
|
||||
|
||||
if (currentVar == RETURN_STAT || currentVar == STOP_STAT || currentVar == EXIT_STMT || currentVar == CONTAINS_STMT)
|
||||
{
|
||||
if (endStatement != currentSt)
|
||||
{
|
||||
interval->ends.push_back(currentSt);
|
||||
interval->exit_levels.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (gotoStmts.find(currentSt->lineNumber()) != gotoStmts.end() && currentVar != LOGIF_NODE)
|
||||
{
|
||||
vector<int>& labels = gotoStmts[currentSt->lineNumber()];
|
||||
|
||||
for (auto& lab : labels)
|
||||
{
|
||||
auto itL = labelsRef.find(lab);
|
||||
if (itL == labelsRef.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
const int label_line = itL->second;
|
||||
if (label_line == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (label_line < interval->begin->lineNumber() || label_line > interval->ends[0]->lineNumber())
|
||||
{
|
||||
interval->ends.push_back(currentSt);
|
||||
interval->exit_levels.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentSt == endStatement || currentVar != FOR_NODE)
|
||||
continue;
|
||||
|
||||
SpfInterval* inter = new SpfInterval(-1);
|
||||
inter->begin = currentSt;
|
||||
inter->ends.push_back(currentSt->lastNodeOfStmt());
|
||||
inter->lineFile = std::make_pair(currentSt->lineNumber(), currentSt->fileName());
|
||||
inter->parent = interval;
|
||||
inter->exit_levels.push_back(0);
|
||||
inter->tag = getNextTag();
|
||||
interval->nested.push_back(inter);
|
||||
|
||||
findIntervals(inter, labelsRef, gotoStmts, currentSt);
|
||||
}
|
||||
}
|
||||
|
||||
void createInterTree(SgFile *file, vector<SpfInterval*> &fileIntervals, bool nested_on, vector<Messages> &messages)
|
||||
{
|
||||
int funcNum = file->numberOfFunctions();
|
||||
|
||||
for (int i = 0; i < funcNum; i++)
|
||||
{
|
||||
map<int, int> labelsRef; // id => line
|
||||
map<int, vector<int>> gotoStmts; // line => label_ids
|
||||
vector<SpfInterval*> userIntervals;
|
||||
|
||||
// Find labels.
|
||||
findAllLabels(file->functions(i), labelsRef);
|
||||
matchGotoLabels(file->functions(i), gotoStmts);
|
||||
|
||||
// Find user intervals.
|
||||
findUserIntervals(file->functions(i), userIntervals, messages);
|
||||
|
||||
SpfInterval *func_inters = new SpfInterval(-1);
|
||||
|
||||
// Set begining of the interval.
|
||||
func_inters->begin = file->functions(i);
|
||||
func_inters->lineFile = std::make_pair(func_inters->begin->lineNumber(), file->functions(i)->fileName());
|
||||
func_inters->tag = getNextTag();
|
||||
|
||||
// Set ending of the interval.
|
||||
SgStatement *lastNode = func_inters->begin->lastNodeOfStmt()->lexPrev();
|
||||
while (isDVM_stat(lastNode) || isSPF_stat(lastNode))
|
||||
lastNode = lastNode->lexPrev();
|
||||
|
||||
SgStatement *prevLastNode = lastNode->lexPrev();
|
||||
while (isDVM_stat(prevLastNode) || isSPF_stat(prevLastNode))
|
||||
prevLastNode = prevLastNode->lexPrev();
|
||||
|
||||
if (lastNode->variant() == RETURN_STAT || lastNode->variant() == EXIT_STMT || lastNode->variant() == STOP_STAT)
|
||||
{
|
||||
bool cond = false;
|
||||
if (lastNode->lexNext()->variant() == CONTROL_END)
|
||||
if (isSgProgHedrStmt(lastNode->lexNext()->controlParent()))
|
||||
cond = true;
|
||||
|
||||
if (cond)
|
||||
func_inters->ends.push_back(lastNode);
|
||||
else
|
||||
func_inters->ends.push_back(prevLastNode);
|
||||
}
|
||||
else
|
||||
func_inters->ends.push_back(lastNode);
|
||||
|
||||
func_inters->exit_levels.push_back(0);
|
||||
|
||||
// Find inner intervals.
|
||||
SgStatement *currentSt = func_inters->begin;
|
||||
findIntervals(func_inters, labelsRef, gotoStmts, currentSt);
|
||||
|
||||
vector<SpfInterval*> oneInterval;
|
||||
oneInterval.push_back(func_inters);
|
||||
|
||||
mergeTrees(oneInterval, userIntervals);
|
||||
calibrateExits(oneInterval, labelsRef, gotoStmts, 1);
|
||||
|
||||
fileIntervals.push_back(oneInterval[0]);
|
||||
}
|
||||
|
||||
if (nested_on)
|
||||
for (auto &interval : fileIntervals)
|
||||
removeNestedIntervals(interval);
|
||||
}
|
||||
|
||||
//SpfInterval insertion funcs
|
||||
static void insertTree(SpfInterval* interval, const string &fileName)
|
||||
{
|
||||
if (interval->ifInclude && interval->begin->fileName() == fileName)
|
||||
{
|
||||
SgStatement* beg_inter = new SgStatement(DVM_INTERVAL_DIR);
|
||||
SgExpression* expr = new SgValueExp(interval->tag);
|
||||
beg_inter->setExpression(0, *expr);
|
||||
|
||||
SgStatement* end_inter = new SgStatement(DVM_ENDINTERVAL_DIR);
|
||||
|
||||
// Skip to executables.
|
||||
SgStatement* beginSt = interval->begin;
|
||||
while (!isSgExecutableStatement(beginSt) || isSPF_stat(beginSt) || isDVM_stat(beginSt))
|
||||
beginSt = beginSt->lexNext();
|
||||
|
||||
if (beginSt->lexPrev()->variant() == LOGIF_NODE)
|
||||
LogIftoIfThen(beginSt->lexPrev());
|
||||
|
||||
// Insert begining
|
||||
beginSt->insertStmtBefore(*beg_inter, *beginSt->controlParent());
|
||||
beg_inter->setlineNumber(beginSt->lineNumber());
|
||||
|
||||
interval->ends[0]->insertStmtAfter(*end_inter, *beginSt->controlParent());
|
||||
|
||||
for (int i = 1; i < interval->ends.size(); i++)
|
||||
{
|
||||
int depth = interval->exit_levels[i];
|
||||
SpfInterval* curr_inter = interval->parent;
|
||||
|
||||
SgExprListExp* expli = new SgExprListExp(*(new SgValueExp(interval->tag)));
|
||||
SgExprListExp* curr_list_elem = expli;
|
||||
|
||||
for (int j = 1; j < depth; j++)
|
||||
{
|
||||
if(curr_inter->ifInclude)
|
||||
{
|
||||
curr_list_elem->setRhs(new SgExprListExp(*(new SgValueExp(curr_inter->tag))));
|
||||
curr_list_elem = curr_list_elem->next();
|
||||
}
|
||||
|
||||
curr_inter = curr_inter->parent;
|
||||
}
|
||||
|
||||
curr_list_elem->setRhs(NULL);
|
||||
SgStatement* exit_inter = new SgStatement(DVM_EXIT_INTERVAL_DIR);
|
||||
exit_inter->setExpression(0, *expli);
|
||||
|
||||
if (interval->ends[i]->lexPrev()->variant() == LOGIF_NODE)
|
||||
LogIftoIfThen(interval->ends[i]->lexPrev());
|
||||
|
||||
interval->ends[i]->insertStmtBefore(*exit_inter, *interval->ends[i]->controlParent());
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < interval->nested.size(); i++)
|
||||
insertTree(interval->nested[i], fileName);
|
||||
}
|
||||
|
||||
void insertIntervals(SgFile *file, const vector<SpfInterval*> &fileIntervals)
|
||||
{
|
||||
const string currFile = file->filename();
|
||||
removeUserIntervals(file);
|
||||
for (auto &interval : fileIntervals)
|
||||
insertTree(interval, currFile);
|
||||
}
|
||||
|
||||
//Profiling funcs
|
||||
static map<int, long long> parseProfiles(fstream &file)
|
||||
{
|
||||
map<int, long long> fileProfile;
|
||||
string line;
|
||||
|
||||
while (!file.eof())
|
||||
{
|
||||
getline(file, line);
|
||||
|
||||
auto pos_type = line.find(":");
|
||||
string type = line.substr(0, pos_type);
|
||||
|
||||
if (type == "lcount")
|
||||
{
|
||||
if ((int)line.size() >= pos_type + 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
string nums = line.substr(pos_type + 1);
|
||||
auto pos_com = nums.find(",");
|
||||
|
||||
auto line_num = stoi(nums.substr(0, pos_com));
|
||||
if ((int)nums.size() >= pos_com + 1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
long long calls_num = stoll(nums.substr(pos_com + 1));
|
||||
|
||||
fileProfile[line_num] = calls_num;
|
||||
}
|
||||
}
|
||||
|
||||
return fileProfile;
|
||||
}
|
||||
|
||||
static void assignRec(SpfInterval* inter, map<int, long long> &fp)
|
||||
{
|
||||
for (int i = 0; i < inter->nested.size(); i++)
|
||||
assignRec(inter->nested[i], fp);
|
||||
|
||||
inter->calls_count = fp[inter->begin->lineNumber()];
|
||||
}
|
||||
|
||||
void assignCallsToFile(const string &baseFilename, vector<SpfInterval*> &intervals)
|
||||
{
|
||||
fstream file;
|
||||
file.open(baseFilename + ".gcov", fstream::in);
|
||||
|
||||
if (!file.good())
|
||||
return;
|
||||
|
||||
map<int, long long> fileProfile = parseProfiles(file);
|
||||
|
||||
file.close();
|
||||
|
||||
for (auto &interval : intervals)
|
||||
assignRec(interval, fileProfile);
|
||||
}
|
||||
|
||||
//Deleting intervals funcs
|
||||
static void removeNode(SpfInterval* inter, long long threshold)
|
||||
{
|
||||
if (inter->calls_count >= threshold)
|
||||
inter->ifInclude = false;
|
||||
|
||||
for (int i = 0; i < inter->nested.size(); i++)
|
||||
removeNode(inter->nested[i], threshold);
|
||||
}
|
||||
|
||||
static void fillListWithValues(list<long long> &interval_calls, SpfInterval* interval)
|
||||
{
|
||||
auto it = interval_calls.begin();
|
||||
|
||||
for(; it != interval_calls.end(); it++)
|
||||
if(interval->calls_count < *it)
|
||||
{
|
||||
interval_calls.insert(it, interval->calls_count);
|
||||
break;
|
||||
}
|
||||
|
||||
if(it == interval_calls.end())
|
||||
interval_calls.push_back(interval->calls_count);
|
||||
|
||||
for (auto &i : interval->nested)
|
||||
fillListWithValues(interval_calls, i);
|
||||
}
|
||||
|
||||
void removeNodes(int threshold, vector<SpfInterval*> &intervals, vector<string> &include_functions)
|
||||
{
|
||||
if (threshold == 100)
|
||||
return;
|
||||
|
||||
for (auto &interval : intervals)
|
||||
{
|
||||
string func_name = interval->begin->symbol()->identifier();
|
||||
|
||||
if (find(include_functions.begin(), include_functions.end(), func_name) != include_functions.end())
|
||||
continue;
|
||||
|
||||
list<long long> interval_calls;
|
||||
fillListWithValues(interval_calls, interval);
|
||||
|
||||
int amount = interval_calls.size() / 100.f * threshold;
|
||||
auto it = interval_calls.begin();
|
||||
advance(it, amount);
|
||||
|
||||
removeNode(interval, *it);
|
||||
}
|
||||
}
|
||||
|
||||
void createMapOfinterval(map<int, SpfInterval*> &mapIntervals, const vector<SpfInterval*> &intervals)
|
||||
{
|
||||
for (auto &inter : intervals)
|
||||
{
|
||||
auto it = mapIntervals.find(inter->begin->lineNumber());
|
||||
if (it != mapIntervals.end())
|
||||
continue;
|
||||
mapIntervals[inter->begin->lineNumber()] = inter;
|
||||
createMapOfinterval(mapIntervals, inter->nested);
|
||||
}
|
||||
}
|
||||
|
||||
void initTimeForIntervalTree(const int numOfTopologies, vector<SpfInterval*> &intervals)
|
||||
{
|
||||
for (auto &inter : intervals)
|
||||
{
|
||||
inter->predictedTimes.resize(numOfTopologies);
|
||||
inter->predictedRemoteTimes.resize(numOfTopologies);
|
||||
|
||||
std::fill(inter->predictedTimes.begin(), inter->predictedTimes.end(), -1);
|
||||
std::fill(inter->predictedRemoteTimes.begin(), inter->predictedRemoteTimes.end(), 0);
|
||||
|
||||
initTimeForIntervalTree(numOfTopologies, inter->nested);
|
||||
}
|
||||
}
|
||||
|
||||
void aggregatePredictedTimes(vector<SpfInterval*> &itervals)
|
||||
{
|
||||
for (auto &interval : itervals)
|
||||
{
|
||||
if (interval->predictedTimes.size() && interval->predictedTimes[0] != -1)
|
||||
continue;
|
||||
|
||||
if (interval->nested.size())
|
||||
aggregatePredictedTimes(interval->nested);
|
||||
|
||||
for (int topo = 0; topo < interval->predictedTimes.size(); ++topo)
|
||||
{
|
||||
double newTimeSum = 0;
|
||||
for (auto &nestedI : interval->nested)
|
||||
{
|
||||
if (nestedI->predictedTimes[topo] == -1)
|
||||
newTimeSum += nestedI->exec_time + nestedI->predictedRemoteTimes[topo];
|
||||
else
|
||||
newTimeSum += nestedI->predictedTimes[topo] + nestedI->predictedRemoteTimes[topo];
|
||||
}
|
||||
interval->predictedTimes[topo] = newTimeSum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SpfInterval* getMainInterval(SgProject *project, const map<string, vector<SpfInterval*>> &intervals, map<string, vector<Messages>> &SPF_messages)
|
||||
{
|
||||
SgStatement *mainUnit = findMainUnit(project, SPF_messages);
|
||||
SpfInterval *mainIterval = NULL;
|
||||
checkNull(mainUnit, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto itMainVec = intervals.find(mainUnit->fileName());
|
||||
if (itMainVec == intervals.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (itMainVec->second.size() == 0)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
else if (itMainVec->second.size() > 1)
|
||||
{
|
||||
for (auto &elem : itMainVec->second)
|
||||
if (elem->begin->variant() == PROG_HEDR)
|
||||
mainIterval = elem;
|
||||
checkNull(mainIterval, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
else
|
||||
mainIterval = itMainVec->second[0];
|
||||
|
||||
return mainIterval;
|
||||
}
|
||||
|
||||
SpfInterval* findNearestUp(const map<SgStatement*, SpfInterval*> &intervals, SgStatement *st)
|
||||
{
|
||||
SpfInterval *found = NULL;
|
||||
|
||||
while (st)
|
||||
{
|
||||
auto it = intervals.find(st);
|
||||
if (it != intervals.end())
|
||||
{
|
||||
found = it->second;
|
||||
break;
|
||||
}
|
||||
else
|
||||
st = st->controlParent();
|
||||
}
|
||||
checkNull(found, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return found;
|
||||
}
|
||||
|
||||
SpfInterval* findNearestDown(const map<SgStatement*, SpfInterval*> &intervals, SgStatement *st)
|
||||
{
|
||||
SpfInterval *found = NULL;
|
||||
|
||||
while (st)
|
||||
{
|
||||
auto it = intervals.find(st);
|
||||
if (it != intervals.end())
|
||||
{
|
||||
found = it->second;
|
||||
break;
|
||||
}
|
||||
else
|
||||
st = st->lexNext();
|
||||
}
|
||||
checkNull(found, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return found;
|
||||
}
|
||||
|
||||
static FuncInfo* getFunc(const string &file, const int line, const map<string, FuncInfo*> &allFuncs)
|
||||
{
|
||||
for (auto &func : allFuncs)
|
||||
if (func.second->linesNum.first == line && func.second->fileName == file)
|
||||
return func.second;
|
||||
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void createMapOfIntervals(const vector<SpfInterval*> &intervals, map<SgStatement*, SpfInterval*> &intervalsBySt)
|
||||
{
|
||||
for (auto &interval : intervals)
|
||||
intervalsBySt[interval->begin] = interval;
|
||||
|
||||
for (auto &interval : intervals)
|
||||
if (interval->nested.size())
|
||||
createMapOfIntervals(interval->nested, intervalsBySt);
|
||||
}
|
||||
|
||||
static void insertAndSort(SpfInterval *nearest, SpfInterval *toInsert, SgStatement *stLine)
|
||||
{
|
||||
if (nearest->nested.size() == 0)
|
||||
nearest->nested.push_back(toInsert);
|
||||
else
|
||||
{
|
||||
const int line = stLine->lineNumber();
|
||||
for (int z = 0; z < nearest->nested.size(); ++z)
|
||||
{
|
||||
if (nearest->nested[z]->parent)
|
||||
{
|
||||
if (nearest->nested[z]->lineFile.first > line)
|
||||
{
|
||||
nearest->nested.insert(nearest->nested.begin() + z, toInsert);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nearest->nested.push_back(toInsert);
|
||||
}
|
||||
}
|
||||
|
||||
void uniteIntervalsBetweenProcCalls(map<string, vector<SpfInterval*>> &intervals, const map<string, vector<FuncInfo*>> &allFuncInfo)
|
||||
{
|
||||
map<string, map<SgStatement*, SpfInterval*>> intervalsBySt;
|
||||
for (auto &byFile : intervals)
|
||||
createMapOfIntervals(byFile.second, intervalsBySt[byFile.first]);
|
||||
|
||||
map<string, FuncInfo*> allFuncs;
|
||||
createMapOfFunc(allFuncInfo, allFuncs);
|
||||
|
||||
for (auto &byFile : intervals)
|
||||
{
|
||||
for (auto &intvl : byFile.second)
|
||||
{
|
||||
if (intvl->begin->variant() != PROG_HEDR)
|
||||
{
|
||||
if (!intvl->begin->switchToFile())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
SgStatement* funcSt = intvl->begin;
|
||||
if (isSgProgHedrStmt(intvl->begin) == NULL)
|
||||
funcSt = intvl->begin->controlParent();
|
||||
const string name = funcSt->symbol()->identifier();
|
||||
auto currF = getFunc(funcSt->fileName(), funcSt->lineNumber(), allFuncs);
|
||||
for (auto &callsTo : currF->callsTo)
|
||||
{
|
||||
if (SgFile::switchToFile(callsTo->fileName) == -1)
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
for (auto &callsInfo: callsTo->callsFromDetailed)
|
||||
{
|
||||
auto& callsFrom = callsInfo.pointerDetailCallsFrom;
|
||||
SgStatement *base = NULL;
|
||||
if (callsFrom.second == PROC_STAT)
|
||||
{
|
||||
base = (SgStatement*)callsFrom.first;
|
||||
if (base->symbol()->identifier() != name)
|
||||
base = NULL;
|
||||
}
|
||||
else if (callsFrom.second == FUNC_CALL)
|
||||
{
|
||||
SgExpression *ex = (SgExpression*)callsFrom.first;
|
||||
if (ex->symbol()->identifier() == name)
|
||||
base = SgStatement::getStatmentByExpression(ex);
|
||||
}
|
||||
|
||||
if (base == NULL)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
auto itI = intervalsBySt.find(callsTo->fileName);
|
||||
if (itI == intervalsBySt.end())
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
auto nearest = findNearestUp(itI->second, base);
|
||||
insertAndSort(nearest, intvl, base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
Sapfor/_src/CreateInterTree/CreateInterTree.h
Normal file
75
Sapfor/_src/CreateInterTree/CreateInterTree.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "dvm.h"
|
||||
|
||||
#include "../GraphLoop/graph_loops_func.h"
|
||||
|
||||
struct SpfInterval
|
||||
{
|
||||
int userIntervalLine;
|
||||
|
||||
int tag = 0;
|
||||
long long calls_count = 0;
|
||||
bool ifInclude = true;
|
||||
|
||||
bool isRegion;
|
||||
bool isNested;
|
||||
|
||||
SgStatement *begin;
|
||||
std::pair<int, std::string> lineFile;
|
||||
SpfInterval *parent;
|
||||
|
||||
std::vector<SgStatement*> ends;
|
||||
std::vector<int> exit_levels;
|
||||
std::vector<SpfInterval*> nested;
|
||||
|
||||
//TODO: to be delete or rewrite with new predictor
|
||||
//from statistic after execution
|
||||
int exec_count = 0;
|
||||
double exec_time = 0;
|
||||
std::vector<double> predictedTimes;
|
||||
std::vector<double> predictedRemoteTimes;
|
||||
|
||||
|
||||
SpfInterval(int line)
|
||||
{
|
||||
userIntervalLine = line;
|
||||
begin = NULL;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
int getBestTimeIdx()
|
||||
{
|
||||
int idx = -1;
|
||||
double best = 0;
|
||||
for (int z = 0; z < predictedTimes.size(); ++z)
|
||||
{
|
||||
if (idx == -1 || best > predictedTimes[z])
|
||||
{
|
||||
best = predictedTimes[z];
|
||||
idx = z;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
};
|
||||
|
||||
void saveIntervals(const std::string &fileName, std::map<std::string, std::vector<SpfInterval*>> &intervals);
|
||||
void createInterTree(SgFile*, std::vector<SpfInterval*>&, bool, std::vector<Messages>&);
|
||||
void assignCallsToFile(const std::string&, std::vector<SpfInterval*>&);
|
||||
void removeNodes(int, std::vector<SpfInterval*>&, std::vector<std::string>&);
|
||||
void insertIntervals(SgFile*, const std::vector<SpfInterval*>&);
|
||||
void createMapOfinterval(std::map<int, SpfInterval*> &mapIntervals, const std::vector<SpfInterval*> &intervals);
|
||||
void initTimeForIntervalTree(const int numOfTopologies, std::vector<SpfInterval*> &intervals);
|
||||
void aggregatePredictedTimes(std::vector<SpfInterval*> &itervals);
|
||||
SpfInterval* getMainInterval(SgProject *project, const std::map<std::string, std::vector<SpfInterval*>> &intervals, std::map<std::string, std::vector<Messages>>& SPF_messages);
|
||||
void uniteIntervalsBetweenProcCalls(std::map<std::string, std::vector<SpfInterval*>> &intervals, const std::map<std::string, std::vector<FuncInfo*>> &allFuncInfo);
|
||||
SpfInterval* findNearestUp(const std::map<SgStatement*, SpfInterval*> &intervals, SgStatement *st);
|
||||
SpfInterval* findNearestDown(const std::map<SgStatement*, SpfInterval*> &intervals, SgStatement *st);
|
||||
Reference in New Issue
Block a user