2025-06-04 13:08:38 +03:00
|
|
|
#include "errors.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
#include "private_variables_analysis.h"
|
2025-06-04 13:08:38 +03:00
|
|
|
#include "graph_loops.h"
|
2023-09-14 19:43:13 +03:00
|
|
|
#include "../LoopAnalyzer/loop_analyzer.h"
|
|
|
|
|
#include "../SageAnalysisTool/depGraph.h"
|
|
|
|
|
#include "../DirectiveProcessing/directive_parser.h"
|
|
|
|
|
#include "live_variable_analysis.h"
|
|
|
|
|
#include "RD_subst.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <map>
|
|
|
|
|
#include <set>
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
|
|
using std::string;
|
|
|
|
|
using std::wstring;
|
|
|
|
|
using std::pair;
|
|
|
|
|
using std::vector;
|
|
|
|
|
using std::map;
|
|
|
|
|
using std::set;
|
|
|
|
|
using std::unordered_set;
|
|
|
|
|
using std::unordered_map;
|
|
|
|
|
using std::list;
|
|
|
|
|
|
|
|
|
|
static map<string, pair<set<int>, set<SAPFOR::Argument*>>> outForFunc;
|
|
|
|
|
static unordered_map<SgSymbol*, string> global_cache, local_cache;
|
|
|
|
|
|
|
|
|
|
static unordered_map <SAPFOR::Argument*, SgSymbol*> argumentToSymbol;
|
|
|
|
|
|
|
|
|
|
#define DEBUG_PRINT_PRIVATE 0
|
|
|
|
|
|
|
|
|
|
#define PRINT_PRIVATES 1
|
|
|
|
|
#define PRINT_WARNINGS 1
|
|
|
|
|
// print privates and lastprivates for loop
|
|
|
|
|
void printLoopInfo(const LoopGraph* loop)
|
|
|
|
|
{
|
|
|
|
|
SgForStmt* loop_stmt = isSgForStmt(loop->loop);
|
|
|
|
|
|
|
|
|
|
const set<string>& priv = loop->privateScalars;
|
|
|
|
|
const set<string>& lastpriv = loop->lastprivateScalars;
|
|
|
|
|
|
|
|
|
|
if(!loop_stmt)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
2025-01-13 18:16:11 +03:00
|
|
|
__spf_print(PRINT_PRIVATES, " loop in file '%s' at line %d\n", loop->fileName.c_str(), loop->lineNum);
|
2023-09-14 19:43:13 +03:00
|
|
|
__spf_print(PRINT_PRIVATES, " privates:");
|
|
|
|
|
for(const auto& ident : priv)
|
|
|
|
|
__spf_print(PRINT_PRIVATES, " %s", ident.c_str());
|
|
|
|
|
__spf_print(PRINT_PRIVATES, "\n lastprivates:");
|
|
|
|
|
for (const auto& ident : lastpriv)
|
|
|
|
|
__spf_print(PRINT_PRIVATES, " %s", ident.c_str());
|
|
|
|
|
__spf_print(PRINT_PRIVATES, "\n");
|
|
|
|
|
|
|
|
|
|
if (PRINT_WARNINGS)
|
|
|
|
|
{
|
|
|
|
|
set<string> added;
|
|
|
|
|
for (auto& data : getAttributes<SgStatement*, SgStatement*>(loop_stmt, set<int>{ SPF_ANALYSIS_DIR }))
|
|
|
|
|
fillPrivatesFromComment(new Statement(data), added);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set<string> extra_old;
|
|
|
|
|
std::set_difference(added.begin(), added.end(), priv.begin(), priv.end(), std::inserter(extra_old, extra_old.begin()));
|
|
|
|
|
|
|
|
|
|
if (extra_old.size() != 0)
|
|
|
|
|
{
|
2025-01-13 18:16:11 +03:00
|
|
|
__spf_print(PRINT_WARNINGS, " [WARNING] extra private variables:");
|
2023-09-14 19:43:13 +03:00
|
|
|
for (const auto& ident : extra_old)
|
|
|
|
|
__spf_print(PRINT_WARNINGS, " %s", ident.c_str());
|
|
|
|
|
__spf_print(PRINT_WARNINGS, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if parent statement contains stmt
|
|
|
|
|
static bool isParentStmt(SgStatement* stmt, SgStatement* parent)
|
|
|
|
|
{
|
|
|
|
|
for (; stmt; stmt = stmt->controlParent())
|
|
|
|
|
if (stmt == parent)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// iterate over expr tree and find SgSymbol that matches arg (by name)
|
|
|
|
|
static SgSymbol* findSymbolByArgInExpression(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, const SAPFOR::Argument* arg, SgExpression* expr)
|
|
|
|
|
{
|
|
|
|
|
if (!expr)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (expr->symbol() && expr->symbol()->identifier() && getArgNameBySymbol(commonVars, func, expr->symbol(), global_cache, local_cache) == arg->getValue())
|
|
|
|
|
return expr->symbol();
|
|
|
|
|
|
|
|
|
|
SgSymbol* left;
|
|
|
|
|
if (left = findSymbolByArgInExpression(commonVars, func, arg, expr->lhs()))
|
|
|
|
|
return left;
|
|
|
|
|
|
|
|
|
|
return findSymbolByArgInExpression(commonVars, func, arg, expr->rhs());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find SgSymbol that matches arg (by name) in stmt
|
|
|
|
|
static SgSymbol* findSymbolByArgInStatement(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, const SAPFOR::Argument* arg, SgStatement* stmt)
|
|
|
|
|
{
|
|
|
|
|
if (!stmt)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (stmt->hasSymbol() && stmt->symbol() &&
|
|
|
|
|
getArgNameBySymbol(commonVars, func, stmt->symbol(), global_cache, local_cache) == arg->getValue())
|
|
|
|
|
{
|
|
|
|
|
return stmt->symbol();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol* found = findSymbolByArgInExpression(commonVars, func, arg, stmt->expr(i));
|
|
|
|
|
if (found)
|
|
|
|
|
return found;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find SgSymbol for arg in instr's operator and fill argumentToSymbol
|
|
|
|
|
// do nothing if arg already has found symbol
|
|
|
|
|
static void addPlaceWithDef(const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func, SAPFOR::Argument* arg, SAPFOR::Instruction* instr) {
|
|
|
|
|
if (argumentToSymbol.find(arg) != argumentToSymbol.end())
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SgStatement* stmt_with_decl = instr->getOperator();
|
|
|
|
|
if (!stmt_with_decl)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
SgSymbol* found = findSymbolByArgInStatement(commonVars, func, arg, stmt_with_decl);
|
|
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
|
argumentToSymbol[arg] = found;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getDefined(const string& func, const vector<SAPFOR::Argument*>& params,
|
|
|
|
|
set<SAPFOR::Argument*>& result)
|
|
|
|
|
{
|
|
|
|
|
if (!joinGlobalsWithParameters(params, outForFunc, func, result))
|
|
|
|
|
{
|
|
|
|
|
if (func == string("_WRITE") || isIntrinsic(func.c_str()))
|
|
|
|
|
return;
|
|
|
|
|
else //READ or else
|
|
|
|
|
insertIfVar(params.begin(), params.end(), result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void fillOutForFunc(const FuncInfo* func, const vector<SAPFOR::BasicBlock*>& blocks)
|
|
|
|
|
{
|
|
|
|
|
if (blocks.size() == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::BasicBlock*> exits = {};
|
|
|
|
|
|
|
|
|
|
for (auto block : blocks)
|
|
|
|
|
{
|
|
|
|
|
if (block->getNext().size() == 0)
|
|
|
|
|
exits.insert(block);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set<int> defined;
|
|
|
|
|
set<SAPFOR::Argument*> common_defined;
|
|
|
|
|
|
|
|
|
|
for (auto byExit : exits)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& byRd : byExit->getRD_Out())
|
|
|
|
|
{
|
|
|
|
|
auto out_arg = byRd.first;
|
|
|
|
|
if (!(byRd.second.size() == 1 && *(byRd.second.begin()) < 0))
|
|
|
|
|
{
|
|
|
|
|
switch (out_arg->getMemType())
|
|
|
|
|
{
|
|
|
|
|
case SAPFOR::CFG_MEM_TYPE::COMMON_:
|
|
|
|
|
case SAPFOR::CFG_MEM_TYPE::MODULE_:
|
|
|
|
|
common_defined.insert(out_arg);
|
|
|
|
|
break;
|
|
|
|
|
case SAPFOR::CFG_MEM_TYPE::FUNC_PARAM_:
|
|
|
|
|
{
|
|
|
|
|
int num = getParamIndex(out_arg, func->funcParams.countOfPars);
|
|
|
|
|
if(func->funcParams.isArgOut(num))
|
|
|
|
|
defined.insert(num);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
outForFunc[func->funcName] = { defined, common_defined };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void getDefsFromBlock(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& res,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const FuncInfo* func)
|
|
|
|
|
{
|
|
|
|
|
vector<SAPFOR::Argument*> lastParamRef;
|
|
|
|
|
|
|
|
|
|
for (auto ir_block : block->getInstructions())
|
|
|
|
|
{
|
|
|
|
|
SAPFOR::Instruction* instr = ir_block->getInstruction();
|
|
|
|
|
SAPFOR::CFG_OP instr_operation = instr->getOperation();
|
|
|
|
|
if (instr_operation == SAPFOR::CFG_OP::PARAM)
|
|
|
|
|
{
|
|
|
|
|
SAPFOR::Argument* arg = instr->getArg1();
|
|
|
|
|
if(arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
|
|
|
|
addPlaceWithDef(commonVars, func, arg, instr);
|
|
|
|
|
|
|
|
|
|
lastParamRef.push_back(arg);
|
|
|
|
|
}
|
|
|
|
|
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
|
|
|
|
|
{
|
|
|
|
|
int count = stoi(instr->getArg2()->getValue());
|
|
|
|
|
if (lastParamRef.size() != count)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
const string& fName = instr->getArg1()->getValue();
|
|
|
|
|
|
|
|
|
|
getDefined(fName, lastParamRef, res);
|
|
|
|
|
|
|
|
|
|
lastParamRef.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int first_instr_num = block->getInstructions().front()->getNumber();
|
|
|
|
|
int last_instr_num = block->getInstructions().back()->getNumber();
|
|
|
|
|
|
|
|
|
|
for (const auto& def : block->getRD_Out())
|
|
|
|
|
for (int place : def.second)
|
|
|
|
|
if (place >= first_instr_num && place <= last_instr_num && def.first->getType() == SAPFOR::CFG_ARG_TYPE::VAR)
|
|
|
|
|
{
|
|
|
|
|
res.insert(def.first);
|
|
|
|
|
addPlaceWithDef(commonVars, func, def.first, block->getInstructions()[place - first_instr_num]->getInstruction());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// recursively analyze FOR loops
|
|
|
|
|
static set<SAPFOR::BasicBlock*> analyzeLoop(LoopGraph* loop, const set<SAPFOR::BasicBlock*>& blocks,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const map<string, SgSymbol*>& commonArgs, FuncInfo* func,
|
|
|
|
|
map<string, vector<Messages>>& messages)
|
|
|
|
|
{
|
2025-06-22 09:19:37 +03:00
|
|
|
if (!loop->isFor())
|
2023-09-14 19:43:13 +03:00
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //should be called only with FOR loops
|
|
|
|
|
|
|
|
|
|
SgStatement* loop_operator = loop->loop->GetOriginal();
|
|
|
|
|
|
|
|
|
|
// find blocks related to the current loop
|
|
|
|
|
set<SAPFOR::BasicBlock*> currentLoop = { };
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
service block that looks like
|
|
|
|
|
_reg = _reg < _reg
|
|
|
|
|
IF_FALSE _reg then goto ...
|
|
|
|
|
*/
|
|
|
|
|
SAPFOR::BasicBlock* head_block = NULL;
|
|
|
|
|
|
|
|
|
|
int loop_start = loop->lineNum, loop_end = loop->lineNumAfterLoop;
|
|
|
|
|
for (auto bb : blocks)
|
|
|
|
|
{
|
|
|
|
|
if (!bb || (bb->getInstructions().size() == 0))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
SgStatement* first = bb->getInstructions().front()->getInstruction()->getOperator();
|
|
|
|
|
SgStatement* last = bb->getInstructions().back()->getInstruction()->getOperator();
|
|
|
|
|
|
|
|
|
|
if (isParentStmt(first, loop_operator) && isParentStmt(last, loop_operator))
|
|
|
|
|
{
|
|
|
|
|
currentLoop.insert(bb);
|
|
|
|
|
|
|
|
|
|
if ((!head_block) && (first == loop_operator) && (last == loop_operator) &&
|
|
|
|
|
(bb->getInstructions().size() == 2) &&
|
|
|
|
|
(bb->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF))
|
|
|
|
|
{
|
|
|
|
|
head_block = bb;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!head_block)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
// find blocks inside loop wich can lead to head_block
|
|
|
|
|
list<SAPFOR::BasicBlock*> search_stack = { head_block };
|
|
|
|
|
set<SAPFOR::BasicBlock*> cycleBody = { };
|
|
|
|
|
|
|
|
|
|
while (search_stack.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
SAPFOR::BasicBlock* curr = search_stack.front();
|
|
|
|
|
search_stack.pop_front();
|
|
|
|
|
|
|
|
|
|
if (cycleBody.insert(curr).second)
|
|
|
|
|
for (auto next : curr->getPrev())
|
|
|
|
|
if (currentLoop.count(next))
|
|
|
|
|
search_stack.push_back(next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::Argument*> useValueInLoop = {};
|
|
|
|
|
|
|
|
|
|
for (const auto& use : head_block->getLiveIn())
|
|
|
|
|
{
|
|
|
|
|
for (SAPFOR::BasicBlock* place : use.second)
|
|
|
|
|
{
|
|
|
|
|
if (currentLoop.count(place))
|
|
|
|
|
{
|
|
|
|
|
useValueInLoop.insert(use.first);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::Argument*> changeValueInLoop = { };
|
|
|
|
|
set<SAPFOR::Argument*> changeValueOnExit = { };
|
|
|
|
|
set<SAPFOR::Argument*> LiveWhenLoopEnds = { };
|
|
|
|
|
|
|
|
|
|
auto loop_it = currentLoop.begin();
|
|
|
|
|
auto loop_end_it = currentLoop.end();
|
|
|
|
|
|
|
|
|
|
auto body_it = cycleBody.begin();
|
|
|
|
|
auto body_end = cycleBody.end();
|
|
|
|
|
|
|
|
|
|
while ((loop_it != loop_end_it) && (body_it != body_end))
|
|
|
|
|
{
|
|
|
|
|
if (*loop_it == *body_it)
|
|
|
|
|
{
|
|
|
|
|
getDefsFromBlock(*loop_it, changeValueInLoop, commonVars, func);
|
|
|
|
|
body_it++;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
getDefsFromBlock(*loop_it, changeValueOnExit, commonVars, func);
|
|
|
|
|
loop_it++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (body_it != body_end)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
for (; loop_it != loop_end_it; loop_it++)
|
|
|
|
|
getDefsFromBlock(*loop_it, changeValueOnExit, commonVars, func);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (auto bb : currentLoop)
|
|
|
|
|
{
|
|
|
|
|
//fill LiveWhenLoopEnds
|
|
|
|
|
bool has_next_outside_body = false;
|
|
|
|
|
for (const auto& next : bb->getNext())
|
|
|
|
|
{
|
|
|
|
|
if (cycleBody.find(next) == cycleBody.end())
|
|
|
|
|
{
|
|
|
|
|
has_next_outside_body = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (has_next_outside_body)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& use : bb->getLiveOut())
|
|
|
|
|
for (SAPFOR::BasicBlock* place : use.second)
|
|
|
|
|
if (currentLoop.count(place) == 0)
|
|
|
|
|
{
|
|
|
|
|
LiveWhenLoopEnds.insert(use.first);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::Argument*> arg_private = {}, arg_lastprivate = {};
|
|
|
|
|
|
|
|
|
|
std::set_difference(changeValueInLoop.begin(), changeValueInLoop.end(),
|
|
|
|
|
useValueInLoop.begin(), useValueInLoop.end(),
|
|
|
|
|
std::inserter(arg_private, arg_private.begin()));
|
|
|
|
|
|
|
|
|
|
arg_private.insert(changeValueOnExit.begin(), changeValueOnExit.end());
|
|
|
|
|
|
|
|
|
|
std::set_intersection(arg_private.begin(), arg_private.end(),
|
|
|
|
|
LiveWhenLoopEnds.begin(), LiveWhenLoopEnds.end(),
|
|
|
|
|
std::inserter(arg_lastprivate, arg_lastprivate.begin()));
|
|
|
|
|
|
|
|
|
|
changeValueInLoop.clear();
|
|
|
|
|
LiveWhenLoopEnds.clear();
|
|
|
|
|
useValueInLoop.clear();
|
|
|
|
|
|
|
|
|
|
vector<const depNode*> sym_private;
|
|
|
|
|
for (auto e : arg_private)
|
|
|
|
|
{
|
|
|
|
|
SgSymbol* arg_sym = NULL;
|
|
|
|
|
|
|
|
|
|
auto it = argumentToSymbol.find(e);
|
|
|
|
|
if (it != argumentToSymbol.end())
|
|
|
|
|
arg_sym = it->second;
|
|
|
|
|
else if (e->getMemType() == SAPFOR::CFG_MEM_TYPE::COMMON_ || e->getMemType() == SAPFOR::CFG_MEM_TYPE::MODULE_)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (arg_sym && arg_sym->identifier())
|
|
|
|
|
{
|
|
|
|
|
if (arg_lastprivate.find(e) != arg_lastprivate.end())
|
|
|
|
|
{
|
|
|
|
|
loop->lastprivateScalars.insert(arg_sym->identifier());
|
|
|
|
|
|
|
|
|
|
const char* identifier = arg_sym->identifier();
|
|
|
|
|
wstring messageE, messageR;
|
|
|
|
|
__spf_printToLongBuf(messageE, L"add lastprivate scalar '%s' to loop on line %d", to_wstring(identifier).c_str(), loop->lineNum);
|
|
|
|
|
__spf_printToLongBuf(messageR, R200, to_wstring(identifier).c_str(), loop->lineNum);
|
|
|
|
|
|
|
|
|
|
messages[loop->fileName].push_back(Messages(NOTE, loop->lineNum, messageR, messageE, 3002));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SgStatement* s = new SgStatement(0);
|
|
|
|
|
s->setlineNumber(loop_start);
|
|
|
|
|
|
|
|
|
|
SgExpression* exp = new SgExpression(VAR_REF);
|
|
|
|
|
exp->setSymbol(arg_sym);
|
|
|
|
|
|
|
|
|
|
sym_private.push_back(new depNode(s, s, exp, exp, 0, 0, NULL, NULL, 0));
|
|
|
|
|
loop->privateScalars.insert(arg_sym->identifier());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
addPrivatesToLoops(loop, sym_private, { {loop_start, isSgForStmt(loop_operator)} }, messages[loop->fileName]);
|
|
|
|
|
|
|
|
|
|
for (const depNode* node : sym_private)
|
|
|
|
|
{
|
|
|
|
|
delete node->stmtin;
|
|
|
|
|
delete node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
arg_private.clear();
|
|
|
|
|
arg_lastprivate.clear();
|
|
|
|
|
|
|
|
|
|
printLoopInfo(loop);
|
|
|
|
|
return currentLoop;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void recAnalyzeLoop(LoopGraph* loop, const set<SAPFOR::BasicBlock*>& blocks,
|
|
|
|
|
const vector<pair<const Variable*, CommonBlock*>>& commonVars,
|
|
|
|
|
const map<string, SgSymbol*>& commonArgs,
|
|
|
|
|
FuncInfo* func, map<string, vector<Messages>>& messages)
|
|
|
|
|
{
|
2025-06-22 09:19:37 +03:00
|
|
|
const auto& loop_body = loop->isFor() ? analyzeLoop(loop, blocks, commonVars, commonArgs, func, messages) : blocks;
|
2023-09-14 19:43:13 +03:00
|
|
|
|
|
|
|
|
for (const auto& inner_loop : loop->children)
|
|
|
|
|
recAnalyzeLoop(inner_loop, loop_body, commonVars, commonArgs, func, messages);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void runPrivateVariableAnalysis(const map<string, vector<LoopGraph*>>& loopGraph,
|
|
|
|
|
const map<FuncInfo*, vector<SAPFOR::BasicBlock*>>& CFGraph_for_project,
|
|
|
|
|
const map<string, CommonBlock*>& commonBlocks,
|
|
|
|
|
map<string, vector<Messages>>& messages)
|
|
|
|
|
{
|
|
|
|
|
map<string, FuncInfo*> funcByName;
|
|
|
|
|
for (const auto& byFunc : CFGraph_for_project)
|
|
|
|
|
if (byFunc.first)
|
|
|
|
|
funcByName[byFunc.first->funcName] = byFunc.first;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//fill outForFunc
|
|
|
|
|
for (const auto& byLoopFunc : loopGraph)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& byLoop : byLoopFunc.second)
|
|
|
|
|
{
|
|
|
|
|
for (const auto& byFuncCall : byLoop->calls)
|
|
|
|
|
{
|
|
|
|
|
const string& fname = byFuncCall.first;
|
|
|
|
|
if (outForFunc.find(fname) == outForFunc.end())
|
|
|
|
|
{
|
|
|
|
|
auto func_it = funcByName.find(fname);
|
|
|
|
|
if (func_it != funcByName.end())
|
|
|
|
|
{
|
|
|
|
|
FuncInfo* func = func_it->second;
|
|
|
|
|
auto cfg_it = CFGraph_for_project.find(func);
|
|
|
|
|
if (cfg_it == CFGraph_for_project.end())
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
|
|
|
|
|
|
|
|
|
fillOutForFunc(cfg_it->first, cfg_it->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
map<FuncInfo*, map<string, SgSymbol*>> commonArgsByFunc = { };
|
|
|
|
|
for (const auto& byFile : loopGraph)
|
|
|
|
|
{
|
|
|
|
|
SgFile::switchToFile(byFile.first);
|
|
|
|
|
|
|
|
|
|
for (auto loop : byFile.second)
|
|
|
|
|
{
|
|
|
|
|
int loop_start = loop->lineNum, loop_end = loop->lineNumAfterLoop;
|
|
|
|
|
|
|
|
|
|
SgStatement* search_func = loop->loop->GetOriginal();
|
|
|
|
|
|
|
|
|
|
while (search_func && (!isSgProgHedrStmt(search_func)))
|
|
|
|
|
search_func = search_func->controlParent();
|
|
|
|
|
|
|
|
|
|
if(!search_func)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //loop statement outside any function statement
|
|
|
|
|
|
|
|
|
|
bool loop_analyzed = false;
|
|
|
|
|
for (const auto& byFunc : CFGraph_for_project)
|
|
|
|
|
{
|
|
|
|
|
if (byFunc.first->fileName == byFile.first && byFunc.first->funcPointer->GetOriginal() == search_func)
|
|
|
|
|
{
|
|
|
|
|
const auto& commonVars = getCommonsByFunction(current_file, byFunc.first->funcPointer, commonBlocks);
|
|
|
|
|
const auto& commonArgs = getCommonArgsByFunc(byFunc.first, commonArgsByFunc, commonVars, global_cache, local_cache);
|
|
|
|
|
|
|
|
|
|
set<SAPFOR::BasicBlock*> loop_ir;
|
|
|
|
|
loop_ir.insert(byFunc.second.begin(), byFunc.second.end());
|
|
|
|
|
recAnalyzeLoop(loop, loop_ir, commonVars, commonArgs, byFunc.first, messages);
|
|
|
|
|
argumentToSymbol.clear(); //clear cache
|
|
|
|
|
loop_analyzed = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!loop_analyzed)
|
|
|
|
|
printInternalError(convertFileName(__FILE__).c_str(), __LINE__); //no func found for loop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local_cache.clear();
|
|
|
|
|
commonArgsByFunc.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outForFunc.clear();
|
|
|
|
|
global_cache.clear();
|
|
|
|
|
}
|