This commit is contained in:
2025-03-12 12:37:19 +03:00
committed by Dudarenko
parent 0c9f0664fd
commit d4fb323f86
428 changed files with 0 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
#pragma once
#include <vector>
#include "dvm.h"
#include "../Utils/errors.h"
void convertFromAssignToLoop(SgFile *file, const std::vector<ParallelRegion*>& regions, std::vector<Messages> &messagesForFile, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void restoreAssignsFromLoop(SgFile *file, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls);
void restoreConvertedLoopForParallelLoops(SgFile *file, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCalls, bool reversed = false);
bool notDeletedVectorAssign(SgStatement* st);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
#pragma once
struct UserFiles
{
std::vector<SgStatement*> placesOpen;
std::vector<SgStatement*> placesClose;
std::vector<SgStatement*> placesWrite;
std::vector<SgStatement*> placesRead;
};
void createCheckpoints(SgFile* file, const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<int, UserFiles>& filesInfo, const std::vector<FuncInfo*>& allFuncInfo);
void convertSaveToModule(SgFile* file);
void preprocessOpenOperators(SgFile* file, std::map<int, UserFiles>& filesInfo);

View File

@@ -0,0 +1,365 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstring>
#include <cstring>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <set>
#include <vector>
#include <algorithm>
#include <tuple>
#include "dvm.h"
#include "convert_to_c.h"
#include "Utils/utils.h"
#include "Utils/SgUtils.h"
using std::vector;
using std::string;
using std::set;
extern "C" void Set_Function_Language(int);
extern "C" void Unset_Function_Language();
extern "C" int out_upper_case;
static SgStatement* createNewFunc(SgSymbol* sF, SgFile* file, SgProgHedrStmt* prog)
{
SgStatement* st_hedr, * st_end;
SgExpression* fe, *arg_list = NULL;
bool isMain = sF == NULL;
if (!sF)
sF = findSymbolOrCreate(file, "main", C_VoidType());
else
sF->setType(C_VoidType());
// create fuction header
st_hedr = new SgStatement(FUNC_HEDR);
st_hedr->setSymbol(*sF);
fe = new SgFunctionRefExp(*sF);
fe->setSymbol(*sF);
st_hedr->setExpression(0, *fe);
// create end of function
st_end = new SgStatement(CONTROL_END);
st_end->setSymbol(*sF);
if (!isMain)
{
//fill global
first_do_par = prog;
fe = st_hedr->expr(0);
int num = prog->numberOfParameters();
for (int z = 0; z < num; ++z)
{
SgSymbol* arg = prog->parameter(z);
auto typ = C_Type(arg->type());
if (arg->type()->variant() == T_STRING)
typ = C_PointerType(SgTypeChar());
auto s = new SgSymbol(VARIABLE_NAME, arg->identifier(), *typ, *st_hedr);
SgExpression* ae = new SgVarRefExp(s);
ae->setType(typ);
if (arg->type()->variant() == T_STRING)
ae = new SgPointerDerefExp(*ae);
if (z == 0)
{
arg_list = new SgExprListExp(*ae);
fe->setLhs(arg_list);
}
else
{
auto el = new SgExpression(EXPR_LIST);
el->setLhs(NULL);
ae->setLhs(*el);
arg_list->setRhs(*new SgExprListExp(*ae));
arg_list = arg_list->rhs();
}
}
first_do_par = NULL;
}
return st_hedr;
}
static void shiftIntValue(SgExpression* ex, SgExpression* par, bool isLeft, const set<string>& for_vars, bool& rep)
{
if (ex)
{
if (ex->variant() == VAR_REF && for_vars.find(ex->symbol()->identifier()) != for_vars.end())
{
if (isLeft)
par->setLhs(*new SgExpression(SUBT_OP, ex->copyPtr(), new SgValueExp(1)));
else
par->setRhs(*new SgExpression(SUBT_OP, ex->copyPtr(), new SgValueExp(1)));
rep = true;
}
shiftIntValue(ex->lhs(), ex, true, for_vars, rep);
shiftIntValue(ex->rhs(), ex, false, for_vars, rep);
}
}
static void findArrayRef(SgExpression* ex, const set<string>& for_vars)
{
if (ex)
{
if (ex->variant() == ARRAY_REF)
{
SgArrayRefExp* ref = (SgArrayRefExp*)ex;
SgExpression* list = ex->lhs();
for (int z = 0; z < ref->numberOfSubscripts(); ++z)
{
bool rep = false;
if (for_vars.size())
shiftIntValue(ref->subscript(z), list, true, for_vars, rep);
if (!rep || for_vars.size() == 0)
{
auto sub = ref->subscript(z);
auto val = isSgValueExp(sub);
if (val && val->isInteger())
val->setValue(val->intValue() - 1);
else
list->setLhs(*new SgExpression(SUBT_OP, sub->copyPtr(), new SgValueExp(1)));
}
list = list->rhs();
}
}
findArrayRef(ex->lhs(), for_vars);
findArrayRef(ex->rhs(), for_vars);
}
}
static void findLoopSymbols(SgExpression* ex, set<string>& vars)
{
if (ex)
{
if (ex->variant() == VAR_REF)
vars.insert(ex->symbol()->identifier());
findLoopSymbols(ex->lhs(), vars);
findLoopSymbols(ex->rhs(), vars);
}
}
void covertToC(SgFile* file)
{
out_upper_case = 0;
int funcNum = file->numberOfFunctions();
SgStatement* global = file->firstStatement();
vector<SgStatement*> funcs;
for (int i = 0; i < funcNum; ++i)
funcs.push_back(file->functions(i));
for (int i = funcs.size() - 1; i >= 0; --i)
{
SgStatement* st = funcs[i];
SgStatement* last = st->lastNodeOfStmt();
//fill global dvm variables
cur_func = st;
bind_ = 1;
//
SgStatement* func = createNewFunc(st->variant() == PROG_HEDR ? NULL : st->symbol()->copyPtr(), file, isSgProgHedrStmt(st));
SgStatement* lastOfFunc = func->lastNodeOfStmt();
global->insertStmtAfter(*func, *global);
set<string> for_vars;
vector<SgStatement*> dvm_dirs;
for (SgStatement* st = funcs[i]; st != last; )
{
if (st->variant() == FOR_NODE)
for_vars.insert(isSgForStmt(st)->doName()->identifier());
else if (st->variant() == CONTROL_END)
{
auto cp = st->controlParent();
if (cp->variant() == FOR_NODE)
for_vars.erase(isSgForStmt(cp)->doName()->identifier());
}
else if (st->variant() == DVM_PARALLEL_ON_DIR)
{
SgExpression* rule = st->expr(2);
findLoopSymbols(rule, for_vars);
}
for (int z = 0; z < 3; ++z)
findArrayRef(st->expr(z), for_vars);
if (isDVM_stat(st))
{
SgStatement* next = st->lexNext();
dvm_dirs.push_back(st->extractStmt());
st = next;
}
else if(st->variant() == ALLOCATE_STMT ||
st->variant() == DEALLOCATE_STMT)
{
SgStatement* next = st->lexNext();
st->extractStmt();
st = next;
}
else
st = st->lexNext();
if (st->variant() == DVM_PARALLEL_ON_DIR)
for_vars.clear();
}
string dvm_comm = "";
int dir_pos = 0;
int dir_line = dvm_dirs.size() ? dvm_dirs[dir_pos]->lineNumber() : -1;
for (SgStatement* st = funcs[i]; st != last; st = st->lexNext())
{
int curr_line = st->lineNumber();
while (dir_line < curr_line && dir_line != -1)
{
SgStatement* dir = dvm_dirs[dir_pos];
if (dir->variant() == DVM_PARALLEL_ON_DIR)
{
vector<SgStatement*> rems;
vector<string> addS;
SgStatement* tmp0 = new SgAssignStmt(*new SgVarRefExp(*new SgSymbol(VARIABLE_NAME, "tmp0")), *dir->expr(0));
SgStatement* tmp2 = new SgAssignStmt(*new SgVarRefExp(*new SgSymbol(VARIABLE_NAME, "tmp2")), *dir->expr(2));
SgExpression* list = dir->expr(1);
while (list)
{
SgExpression* item = list->lhs();
if (item->variant() != REMOTE_ACCESS_OP)
{
string s = item->unparse();
convertToLower(s);
addS.push_back(s);
}
else
rems.push_back(new SgAssignStmt(*new SgVarRefExp(*new SgSymbol(VARIABLE_NAME, "tmp1")), *item->lhs()));
list = list->rhs();
}
SgCExpStmt* conv0 = (SgCExpStmt*)Translate_Fortran_To_C(tmp0, true);
SgCExpStmt* conv2 = (SgCExpStmt*)Translate_Fortran_To_C(tmp2, true);
Set_Function_Language(C_LANG);
string array = conv0->expr()->rhs()->unparse();
string rule = conv2->expr()->rhs()->unparse();
for (auto& conv : rems)
{
SgCExpStmt* convE = (SgCExpStmt*)Translate_Fortran_To_C(conv, true);
string s = convE->expr()->rhs()->unparse();
convertToLower(s);
addS.push_back(string("remote_access(") + s + ")");
}
Unset_Function_Language();
char buf[1024];
sprintf(buf, "#pragma dvm parallel([%s] on %s) ", rule.c_str(), array.c_str());
string pragma = buf;
for (int z = 0; z < addS.size(); ++z)
{
pragma += addS[z];
if (z != addS.size() - 1)
pragma += ", ";
}
if (dvm_comm.size())
dvm_comm += "\n";
dvm_comm += pragma;
}
else if (dir->variant() == ACC_END_REGION_DIR)
{
if (dvm_comm.size())
dvm_comm += "\n";
dvm_comm += " }";
}
else if (dir->variant() == ACC_REGION_DIR)
{
if (dvm_comm.size())
dvm_comm += "\n";
string type = "";
if (dir->expr(0))
{
type = dir->expr(0)->unparse();
convertToLower(type);
}
dvm_comm += string("#pragma dvm region ") + type + "\n";
dvm_comm += " {";
}
else if (dir->variant() == ACC_GET_ACTUAL_DIR)
{
if (dvm_comm.size())
dvm_comm += "\n";
SgStatement* tmp0 = new SgAssignStmt(*new SgVarRefExp(*new SgSymbol(VARIABLE_NAME, "tmp0")), *dir->expr(0));
SgCExpStmt* conv0 = (SgCExpStmt*)Translate_Fortran_To_C(tmp0, true);
Set_Function_Language(C_LANG);
string array = conv0->expr()->rhs()->unparse();
Unset_Function_Language();
dvm_comm += "#pragma dvm get_actual(" + array + ")";
}
dir_pos++;
dir_line = (dir_pos < dvm_dirs.size()) ? dvm_dirs[dir_pos]->lineNumber() : -1;
}
if (isSgExecutableStatement(st))
{
SgStatement* conv = Translate_Fortran_To_C(st, true);
if (st->comments())
{
string str(st->comments());
vector<string> result;
splitString(str, '\n', result);
str = "";
for (int z = 0; z < result.size(); ++z)
{
str += "//" + result[z].substr(1, result[z].size());
if (z != result.size() - 1)
str += "\n";
}
conv->addComment(str.c_str());
}
if (dvm_comm.size())
{
conv->addComment(dvm_comm.c_str());
dvm_comm.clear();
}
lastOfFunc->insertStmtBefore(*conv, *func);
//printf("on line %d\n%s\n", st->lineNumber(), conv->unparse(C_LANG));
st = st->lastNodeOfStmt();
}
}
funcs[i]->extractStmt();
}
/*string includes;
includes += "#include <math.h>\n";
includes += "#include <stdlib.h>\n";
includes += "#include <stdio.h>\n";
global->addComment(includes.c_str());*/
FILE* file_out = fopen((OnlyName(file->filename()) + ".cdv").c_str(), "w");
fprintf(file_out, "%s\n", global->unparse(C_LANG));
fclose(file_out);
}

View File

@@ -0,0 +1,3 @@
#pragma once
void covertToC(SgFile* file);

View File

@@ -0,0 +1,631 @@
#include "dead_code.h"
#include <map>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using std::map;
using std::string;
using std::vector;
using std::set;
using std::remove_if;
#define PRINT_USELESS_STATEMENTS 1
#define DEBUG_IR 0
static void updateUseDefForInstruction(SAPFOR::BasicBlock* block, SAPFOR::Instruction* instr,
set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters,
vector<SAPFOR::Argument*>& arg_stack, int& arg_stack_index, int& arg_stack_size,
string& fName, const map<string, FuncInfo*>& funcByName,
bool& useful, bool& last_stack_op_useful,
set<SAPFOR::Argument*>& usedByThisBlock)
{
set<SAPFOR::Argument*> res, args;
bool last_stack_op;
vector<LIVE_VARIABLES::LiveDeadVarsForCall> fcalls;
getUseDefForInstruction(block, instr,
args, res,
formal_parameters, fcalls,
arg_stack, arg_stack_index, arg_stack_size,
last_stack_op,
fName, funcByName,
false
);
const auto instr_operation = instr->getOperation();
if (!useful)
{
for (SAPFOR::Argument* r : res)
{
if (use.find(r) != use.end() ||
r->getMemType() != SAPFOR::CFG_MEM_TYPE::LOCAL_ ||
!(r->getType() == SAPFOR::CFG_ARG_TYPE::VAR || r->getType() == SAPFOR::CFG_ARG_TYPE::REG))
{
useful = true;
break;
}
}
}
if (!useful)
{
static const set<SAPFOR::CFG_OP> always_useful =
{
SAPFOR::CFG_OP::POINTER_ASS,
SAPFOR::CFG_OP::STORE,
SAPFOR::CFG_OP::REC_REF_STORE,
SAPFOR::CFG_OP::RANGE,
SAPFOR::CFG_OP::ENTRY,
SAPFOR::CFG_OP::EXIT,
SAPFOR::CFG_OP::DVM_DIR,
SAPFOR::CFG_OP::SPF_DIR,
SAPFOR::CFG_OP::IO_PARAM
};
if (always_useful.find(instr_operation) != always_useful.end())
useful = true;
else if (instr_operation == SAPFOR::CFG_OP::F_CALL)
{
auto func_it = funcByName.find(instr->getArg1()->getValue());
useful |= func_it == funcByName.end() || !(func_it->second->isPure);
}
else if (instr_operation == SAPFOR::CFG_OP::PARAM ||
instr_operation == SAPFOR::CFG_OP::REF)
useful |= last_stack_op_useful;
}
if (useful)
{
if (instr_operation == SAPFOR::CFG_OP::F_CALL ||
instr_operation == SAPFOR::CFG_OP::LOAD ||
instr_operation == SAPFOR::CFG_OP::STORE)
last_stack_op_useful = true;
for (auto e : res)
{
def.insert(e);
use.erase(e);
}
for (auto e : args)
{
use.insert(e);
def.erase(e);
}
usedByThisBlock.insert(args.begin(), args.end());
}
if (last_stack_op)
last_stack_op_useful = false;
}
//Build use and def sets of block. Result are stored in use and def
static void buildUseDef(SAPFOR::BasicBlock* block, set<SAPFOR::Argument*>& use, set<SAPFOR::Argument*>& def,
vector<SAPFOR::Argument*>& formal_parameters, vector<bool>& useful,
set<SAPFOR::Argument*>& usedByThisBlock, const map<string, FuncInfo*>& funcByName)
{
set<SAPFOR::Argument*> use_with_regs = use, def_with_regs = def;
vector<SAPFOR::Argument*> arg_stack;
int arg_stack_index = 0, arg_stack_size = 0;
string fName = "";
bool last_fcall_useful = false;
const auto& instructions = block->getInstructions();
int instr_size = instructions.size();
for (int i = instr_size - 1; i >= 0; i--)
{
bool u = useful[i];
updateUseDefForInstruction(block, instructions[i]->getInstruction(),
use_with_regs, def_with_regs,
formal_parameters,
arg_stack, arg_stack_index, arg_stack_size,
fName, funcByName,
u, last_fcall_useful,
usedByThisBlock
);
useful[i] = u;
}
use.insert(use_with_regs.begin(), use_with_regs.end());
def.insert(def_with_regs.begin(), def_with_regs.end());
}
class DeadCodeAnalysisNode : public DataFlowAnalysisNode<map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>>
{
private:
vector<bool> useful;
bool useful_block = false;
set<DeadCodeAnalysisNode*> next_notempty_in, next_notempty_out;
bool useful_jump = false;
vector<SAPFOR::Argument*>& formal_parameters;
const map<string, FuncInfo*>& funcByName;
public:
bool updateJumpStatus()
{
bool res = false;
const auto& prev = getPrevBlocks();
if (prev.size() > 1 && !useful.back() &&
getBlock()->getInstructions().back()->getInstruction()->getOperation() == SAPFOR::CFG_OP::JUMP_IF)
{
const auto& example = dynamic_cast<DeadCodeAnalysisNode*>(*prev.begin())->next_notempty_out;
for (auto p : prev)
{
DeadCodeAnalysisNode* next = dynamic_cast<DeadCodeAnalysisNode*>(p);
if (next->next_notempty_out != example)
{
useful.back() = true;
res = true;
break;
}
}
}
return res;
}
bool updateNextNotEmpty()
{
bool updated = false;
if(!useful_block)
{
set<DeadCodeAnalysisNode*> current = {};
for (auto nextP : getPrevBlocks())
{
DeadCodeAnalysisNode* next = dynamic_cast<DeadCodeAnalysisNode*>(nextP);
if(!next)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
current.insert(next->next_notempty_out.begin(), next->next_notempty_out.end());
}
if (current != next_notempty_in)
{
next_notempty_in = current;
updated = true;
}
}
return updated;
}
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getIn()
{
return getBlock()->getLiveOut();
}
map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>> getOut()
{
return getBlock()->getLiveIn();
}
bool addIn(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
return getBlock()->addLiveOut(data);
}
bool addOut(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
return getBlock()->addLiveIn(data);
}
bool updateState()
{
bool updated = false;
if (!useful_block)
updated |= updateNextNotEmpty();
if (!useful_block)
{
if (next_notempty_in != next_notempty_out)
{
updated = true;
next_notempty_out = next_notempty_in;
}
}
updated |= updateJumpStatus();
if(updated)
this->forwardData({ });
return updated;
}
DATA_FLOW_UPD_STATUS forwardData(const map<SAPFOR::Argument*, vector<SAPFOR::BasicBlock*>>& data)
{
bool inserted_prop = false, inserted_gen = false;
SAPFOR::BasicBlock* bb = getBlock();
set<SAPFOR::Argument*> use, def;
for (const auto& byArg : data)
use.insert(byArg.first);
set<SAPFOR::Argument*> usedByThisBlock;
buildUseDef(bb, use, def, this->formal_parameters, useful, usedByThisBlock, funcByName);
auto in = bb->getLiveIn(), out = bb->getLiveOut();
for (SAPFOR::Argument* arg : use)
{
if(arg && (arg->getType() == SAPFOR::CFG_ARG_TYPE::VAR || arg->getType() == SAPFOR::CFG_ARG_TYPE::REG))
{
bool this_block = usedByThisBlock.find(arg) != usedByThisBlock.end();
if (!this_block)
{
auto data_it = data.find(arg);
if (data_it == data.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
inserted_prop |= bb->addLiveIn({ *data_it });
}
else
{
auto in_it = in.find(arg);
bool skip = false;
if (in_it != in.end())
{
if (in_it->second.size() == 1 && *(in_it->second.begin()) == bb)
skip = true; // nothing to do, inserted = false
else
bb->removeLiveIn(arg);
}
if(!skip)
inserted_gen |= bb->addLiveIn({ { arg, { bb } } });
}
}
}
if(!useful_block)
{
for(bool status : useful)
{
if (status)
{
useful_block = true;
inserted_gen = true;
next_notempty_out = { this };
break;
}
}
}
if(inserted_gen)
return DATA_FLOW_UPD_STATUS::GENERATED;
else if(inserted_prop)
return DATA_FLOW_UPD_STATUS::PROPAGATED;
return DATA_FLOW_UPD_STATUS::NO_CHANGE;
}
DeadCodeAnalysisNode(SAPFOR::BasicBlock* block,
vector<SAPFOR::Argument*>& formal_parameters,
const map<string, FuncInfo*>& funcByName)
:
formal_parameters(formal_parameters),
funcByName(funcByName)
{
setBlock(block);
useful.resize(block->getInstructions().size(), false);
this->forwardData({ });
}
const vector<bool>& getResult() { return useful; }
};
class DeadCodeAnalysis : public BackwardDataFlowAnalysis<DeadCodeAnalysisNode>
{
protected:
vector<SAPFOR::Argument*>& formal_parameters;
const map<string, FuncInfo*>& funcByName;
DeadCodeAnalysisNode* createNode(SAPFOR::BasicBlock* block) override
{
return new DeadCodeAnalysisNode(block, formal_parameters, funcByName);
}
public:
DeadCodeAnalysis(vector<SAPFOR::Argument*>& formal_parameters,
const map<string, FuncInfo*>& funcByName)
:
formal_parameters(formal_parameters),
funcByName(funcByName)
{ }
};
static bool hasCalls(SgExpression* ex)
{
if (ex)
{
if (ex->variant() == FUNC_CALL)
return true;
return hasCalls(ex->lhs()) || hasCalls(ex->rhs());
}
return false;
}
//TODO: add check for side effects for function calls
static bool hasCalls(SgStatement* stat)
{
if (stat->variant() == FOR_NODE)
{
auto forSt = isSgForStmt(stat);
return hasCalls(forSt->start()) || hasCalls(forSt->end()) || hasCalls(forSt->step());
}
else
return hasCalls(stat->expr(0)) || hasCalls(stat->expr(1)) || hasCalls(stat->expr(2));
}
static void moveComment(SgStatement* stat)
{
const char* comm = stat->comments();
if (comm)
{
SgStatement* next = stat->lastNodeOfStmt()->lexNext();
if (next)
{
const char* commNext = next->comments();
if (commNext)
{
string newComm(comm);
newComm += commNext;
next->delComments();
next->addComment(newComm.c_str());
}
else
next->addComment(comm);
}
}
}
int removeDeadCode(SgStatement* func,
const map<string, vector<FuncInfo*>>& allFuncs,
const map<string, CommonBlock*>& commonBlocks,
SgStatement* intervalDelStart, SgStatement* intervalDelEnd)
{
int countOfTransform = 0;
if (intervalDelStart && !intervalDelEnd || !intervalDelStart && intervalDelEnd)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgProgHedrStmt* prog = isSgProgHedrStmt(func);
if (intervalDelStart)
if (intervalDelStart->lineNumber() < prog->lineNumber() || intervalDelStart->lineNumber() > prog->lastNodeOfStmt()->lineNumber())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
if (intervalDelEnd)
if (intervalDelEnd->lineNumber() < prog->lineNumber() || intervalDelEnd->lineNumber() > prog->lastNodeOfStmt()->lineNumber())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto cfg = buildCFGforCurrentFunc(func, SAPFOR::CFG_Settings(true, false, false, false, false, false, false), commonBlocks, allFuncs);
if(cfg.size() != 1)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto& cfg_pair = *(cfg.begin());
// delete unreachable blocks
set<SAPFOR::BasicBlock*> reachable;
for (auto b : cfg_pair.second)
if(b->getInstructions().front()->isHeader() ||
b->getInstructions().front()->getInstruction()->getOperation() == SAPFOR::CFG_OP::ENTRY)
reachable.insert(b);
set<SAPFOR::BasicBlock*> worklist = reachable;
while (worklist.size() != 0)
{
set<SAPFOR::BasicBlock*> to_insert;
for(auto b : worklist)
for(auto next: b->getNext())
if(reachable.insert(next).second)
to_insert.insert(next);
worklist = to_insert;
}
auto remove_unreachable_it = remove_if(cfg_pair.second.begin(), cfg_pair.second.end(),
[&reachable](SAPFOR::BasicBlock* b)
{
if (reachable.find(b) == reachable.end())
{
for(auto next: b->getNext())
if(reachable.find(next) != reachable.end())
next->removePrev(b);
delete b;
return true;
}
return false;
}
);
reachable.clear();
cfg_pair.second.erase(remove_unreachable_it, cfg_pair.second.end());
#if DEBUG_IR
dumpCFG({ cfg_pair }, false);
#endif
// detect useless code
vector<SAPFOR::Argument*> func_parameters(cfg_pair.first->funcParams.countOfPars, NULL);
map<string, FuncInfo*> funcByName;
for (auto& byFile : allFuncs)
for (auto byFunc : byFile.second)
funcByName[byFunc->funcName] = byFunc;
DeadCodeAnalysis analysis_object(func_parameters, funcByName);
analysis_object.fit(cfg_pair.second);
analysis_object.analyze();
// detect dead statements
set<SgStatement*> useful;
for (DeadCodeAnalysisNode* byNode : analysis_object.getNodes())
{
const auto& instructions = byNode->getBlock()->getInstructions();
const auto& statuses = byNode->getResult();
int size = instructions.size();
if(size != statuses.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < size; i++)
{
if(statuses[i])
{
SgStatement* stmt = instructions[i]->getInstruction()->getOperator();
while(stmt && useful.insert(stmt).second)
stmt = stmt->controlParent();
}
}
}
// remove dead statements
static const set<int> removable =
{
ASSIGN_STAT,
PROC_STAT,
WRITE_STAT,
READ_STAT
};
vector<SgStatement*> remove;
SgStatement* start = intervalDelStart ? intervalDelStart : func;
SgStatement* end = intervalDelEnd ? intervalDelEnd : func->lastNodeOfStmt();
for (auto st = start; st != end; st = st->lexNext())
{
const int var = st->variant();
if (removable.find(var) != removable.end() && useful.find(st) == useful.end())
{
remove.push_back(st);
st = st->lastNodeOfStmt();
}
if (var == CONTAINS_STMT)
break;
}
for (auto& rem : remove)
{
__spf_print(PRINT_USELESS_STATEMENTS, "[Useless statement on line %d and file %s]\n", rem->lineNumber(), rem->fileName());
auto cp = rem->controlParent();
if (cp->variant() == LOGIF_NODE)
{
if (hasCalls(cp))
{
((SgLogIfStmt*)cp)->convertLogicIf();
rem->deleteStmt();
}
else
{
moveLabelBefore(cp);
moveComment(cp);
cp->deleteStmt();
}
}
else
{
moveLabelBefore(rem);
moveComment(rem);
rem->deleteStmt();
}
}
countOfTransform += remove.size();
//remove empty blocks
do
{
remove.clear();
for (auto st = start; st != end; st = st->lexNext())
{
const int var = st->variant();
if ((var == FOR_NODE || var == WHILE_NODE || var == SWITCH_NODE) &&
st->lexNext()->variant() == CONTROL_END)
{
if (!hasCalls(st))
remove.push_back(st);
}
else if (var == IF_NODE)
{
if (!hasCalls(st))
{
bool hasCalls_ = false;
SgStatement* ifS = st;
while (ifS->lexNext()->variant() == ELSEIF_NODE)
{
hasCalls_ |= hasCalls(ifS->lexNext());
ifS = ifS->lexNext();
}
SgStatement* lastNode = ifS->lastNodeOfStmt();
ifS = ifS->lexNext();
while (ifS->variant() == CONTROL_END && ifS != lastNode)
ifS = ifS->lexNext();
if (ifS == lastNode && !hasCalls_)
remove.push_back(st);
}
}
//TODO: other block statements
if (var == CONTAINS_STMT)
break;
}
bool mainRemoved = false;
for (auto& rem : remove)
{
__spf_print(PRINT_USELESS_STATEMENTS, "[Useless block statement on line %d and file %s]\n", rem->lineNumber(), rem->fileName());
moveLabelBefore(rem);
moveComment(rem);
rem->deleteStmt();
if (rem == start)
mainRemoved = true;
}
countOfTransform += remove.size();
if (mainRemoved)
break;
} while (remove.size());
deleteCFG(cfg);
return countOfTransform;
}

View File

@@ -0,0 +1,15 @@
#pragma once
#include<string>
#include<vector>
#include "../Utils/SgUtils.h"
#include "../CFGraph/CFGraph.h"
#include "../CFGraph/live_variable_analysis.h"
#include "../CFGraph/DataFlow/data_flow.h"
#include "../CFGraph/DataFlow/backward_data_flow.h"
int removeDeadCode(SgStatement* func,
const std::map<std::string, std::vector<FuncInfo*>>&allFuncs,
const std::map<std::string, CommonBlock*>& commonBlocks,
SgStatement* intervalDelStart = NULL, SgStatement* intervalDelEnd = NULL);

View File

@@ -0,0 +1,468 @@
#include "../Utils/leak_detector.h"
#include <cstdio>
#include <cstring>
#include <cstring>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <set>
#include <vector>
#include "dvm.h"
#include "enddo_loop_converter.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../Utils/SgUtils.h"
using namespace std;
static vector<Messages> *currMessages;
static set<int> allLables;
static void copyLabelAndComents(SgStatement *from, SgStatement *to)
{
if (from->hasLabel())
to->setLabel(*from->label());
if (from->comments())
to->setComments(from->comments());
}
static SgLabel* getUniqLabel(unsigned was)
{
while (1)
{
was++;
if (allLables.find(was) == allLables.end())
break;
}
SgLabel *ret = new SgLabel(was);
return ret;
}
static vector<SgStatement*> convertArithIf(SgStatement *curr)
{
SgExpression *cond = curr->expr(0);
SgExpression *lb = curr->expr(1);
SgLabel *arith_lab[3];
int i = 0;
while (lb)
{
SgLabel *lab = ((SgLabelRefExp *)(lb->lhs()))->label();
arith_lab[i] = lab;
i++;
lb = lb->rhs();
}
SgStatement *replaceSt;
SgType *type = NULL;
if (cond->type())
type = cond->type();
else
type = SgTypeInt();
auto condS = new SgSymbol(VARIABLE_NAME, ("ar_If_C" + std::to_string(curr->lineNumber())).c_str(), type, curr->getScopeForDeclare());
SgStatement *assignCond = new SgAssignStmt(*new SgVarRefExp(*condS), *cond);
vector<SgSymbol*> toAdd = { condS };
makeDeclaration(curr, toAdd);
if (arith_lab[1]->getLabNumber() == arith_lab[2]->getLabNumber())
replaceSt = new SgIfStmt(*new SgVarRefExp(*condS) < *new SgValueExp(0), *new SgGotoStmt(*arith_lab[0]), *new SgGotoStmt(*arith_lab[1]));
else
replaceSt = new SgIfStmt(*new SgVarRefExp(*condS) < *new SgValueExp(0),
*new SgGotoStmt(*arith_lab[0]),
*new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp(0), *new SgGotoStmt(*arith_lab[1]), *new SgGotoStmt(*arith_lab[2])));
return { assignCond, replaceSt };
}
static vector<SgStatement*> convertComGoto(SgStatement *curr)
{
SgExpression *cond = curr->expr(1);
SgExpression *lb = curr->expr(0);
vector<SgLabel*> labs;
while (lb)
{
labs.push_back(((SgLabelRefExp *)(lb->lhs()))->label());
lb = lb->rhs();
}
SgStatement *replace = NULL;
auto condS = new SgSymbol(VARIABLE_NAME, ("com_Goto_C" + std::to_string(curr->lineNumber())).c_str(), SgTypeInt(), curr->getScopeForDeclare());
SgStatement *assignCond = new SgAssignStmt(*new SgVarRefExp(*condS), *cond);
vector<SgSymbol*> toAdd = { condS };
makeDeclaration(curr, toAdd);
if (labs.size() == 1)
replace = new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp(1), *new SgGotoStmt(*labs[0]));
else
replace = new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp((int)labs.size()), *new SgGotoStmt(*labs.back()));
for (int z = (int)labs.size() - 2; z >= 0; --z)
replace = new SgIfStmt(*new SgVarRefExp(*condS) == *new SgValueExp(z + 1), *new SgGotoStmt(*labs[z]), *replace);
return { assignCond, replace };
}
static pair<SgStatement*, SgStatement*> convertForall(SgStatement *st)
{
if (st->variant() != FORALL_NODE && st->variant() != FORALL_STAT)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgForStmt *ret = NULL;
SgExpression *ex = st->expr(0);
SgExpression *cond = st->expr(1);
vector<pair<SgSymbol*, tuple<SgExpression*, SgExpression*, SgExpression*>>> loops;
SgSymbol* construct = NULL;
if (BIF_LL3(st->thebif))
construct = SymbMapping(NODE_SYMB(BIF_LL3(st->thebif)));
while (ex)
{
if (ex->lhs()->variant() != FORALL_OP)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgExpression *left = ex->lhs();
if (left->lhs()->lhs()->variant() == DDOT)
loops.push_back(make_pair(left->symbol(), make_tuple(left->lhs()->lhs()->lhs(), left->lhs()->lhs()->rhs(), left->lhs()->rhs())));
else
loops.push_back(make_pair(left->symbol(), make_tuple(left->lhs()->lhs(), left->lhs()->rhs(), (SgExpression*)NULL)));
ex = ex->rhs();
}
SgStatement *insertPoint = NULL;
for (int z = loops.size() - 1; z >= 0; --z)
{
if (z == loops.size() - 1)
{
SgIfStmt *condIf = cond == NULL ? NULL : new SgIfStmt(*cond);
ret = new SgForStmt(loops[z].first, get<0>(loops[z].second), get<1>(loops[z].second), get<2>(loops[z].second), condIf);
if (condIf)
insertPoint = condIf;
else
insertPoint = ret;
}
else
ret = new SgForStmt(loops[z].first, get<0>(loops[z].second), get<1>(loops[z].second), get<2>(loops[z].second), ret);
}
if (construct)
ret->setConstructName(construct);
return make_pair(ret, insertPoint);
}
template<vector<SgStatement*> funcConv(SgStatement*)>
static void convert(SgStatement *&curr, const wstring &messageE, const wstring &messageR)
{
const int lineNum = curr->lineNumber();
vector<SgStatement*> replaceSt = funcConv(curr);
if (curr->controlParent()->variant() == LOGIF_NODE)
LogIftoIfThen(curr->controlParent());
for (int k = (int)replaceSt.size() - 1; k >= 0; --k)
curr->insertStmtAfter(*(replaceSt[k]), *curr->controlParent());
copyLabelAndComents(curr, curr->lexNext());
SgStatement *toDel = curr;
curr = curr->lexNext();
toDel->deleteStmt();
//TODO
//char buf[512];
//sprintf(buf, (to_string(messageE) + " on line %d\n").c_str(), lineNum);
//addToGlobalBufferAndPrint(buf);
currMessages->push_back(Messages(NOTE, lineNum, messageR, messageE, 2002));
}
static void tryToCorrectLoop(SgForStmt *&forSt, map<SgForStmt*, SgLabel*> &endOfLoops)
{
SgLabel *tmp = endOfLoops[forSt];
SgStatement *curr = forSt->lexNext();
SgStatement *lastNode;
// find the last node of this FOR with label
while (curr)
{
if (curr->hasLabel())
if (curr->label() == tmp)
break;
curr = curr->lexNext();
}
lastNode = curr;
// replace last node with CONTINUE with NEW label and replace all FOR labels to new label
lastNode->insertStmtAfter(*new SgContinueStmt(), *(curr->controlParent()));
SgStatement *next = lastNode->lexNext();
SgLabel *newLab = getUniqLabel(curr->label()->getLabNumber());
next->setLabel(*newLab);
lastNode = next;
curr = forSt;
while (curr != lastNode)
{
if (curr->variant() == FOR_NODE || curr->variant() == WHILE_NODE)
{
SgLabel *currLab = ((SgForStmt*)curr)->endOfLoop();
if (currLab)
if (currLab->getLabNumber() == tmp->getLabNumber())
BIF_LABEL_USE(curr->thebif) = newLab->thelabel;
}
curr = curr->lexNext();
}
curr = forSt->lexNext();
// convert all arithmetic if and computed goto to simple if with goto
//TODO: add ASSIGN GOTO
while (curr != lastNode)
{
wstring bufR = L"";
if (curr->variant() == ARITHIF_NODE)
{
convert<convertArithIf>(curr, L"convert arithmetic IF to simple IF", R96);
continue;
}
else if (curr->variant() == COMGOTO_NODE)
{
convert<convertComGoto>(curr, L"convert computed GOTO to simple IF", R97);
continue;
}
else if (curr->variant() == ASSGOTO_NODE)
{
SgExpression *lb = curr->expr(0);
SgSymbol *assignedS = curr->symbol();
//TODO
}
curr = curr->lexNext();
}
}
static void tryToConverLoop(SgForStmt *&forSt, map<SgForStmt*, SgLabel*> &endOfLoops)
{
const int lineNum = forSt->lineNumber();
if (forSt->isEnddoLoop() == false)
{
int result = forSt->convertLoop();
if (result == 0)
{
tryToCorrectLoop(forSt, endOfLoops);
result = forSt->convertLoop();
if (result == 0)
{
char buf[512];
sprintf(buf, "ERROR: can not convert to END DO loop on line %d\n", lineNum);
addToGlobalBufferAndPrint(buf);
currMessages->push_back(Messages(ERROR, lineNum, R98, L"can not convert to END DO loop", 2003));
}
}
if (result > 0)
{
char buf[512];
sprintf(buf, "convert to END DO loop on line %d\n", lineNum);
addToGlobalBufferAndPrint(buf);
currMessages->push_back(Messages(NOTE, lineNum, R99 , L"convert to END DO loop", 2004));
}
}
}
static void getAllLabels(SgFile *file)
{
allLables.clear();
int funcNum = file->numberOfFunctions();
for (int i = 0; i < funcNum; ++i)
{
SgStatement *st = file->functions(i);
SgStatement *lastNode = st->lastNodeOfStmt();
while (st && st != lastNode)
{
if (st->hasLabel())
{
SgLabel *lab = st->label();
if (lab)
allLables.insert(lab->getLabNumber());
}
st = st->lexNext();
}
}
}
static void fillEndOfLoop(SgStatement *st, map<SgForStmt*, SgLabel*> &endOfLoops, map<int, SgForStmt*> &toProcessLoops)
{
SgStatement *lastNode = st->lastNodeOfStmt();
while (st && st != lastNode)
{
if (st->variant() == CONTAINS_STMT)
break;
if (st->variant() == FOR_NODE)
{
SgForStmt *forSt = (SgForStmt*)st;
if (forSt->isEnddoLoop() == false)
{
SgLabel *endOfLoop = forSt->endOfLoop();
if (endOfLoop != NULL)
{
endOfLoops[forSt] = endOfLoop;
auto it = toProcessLoops.find(endOfLoop->getLabNumber());
if (it == toProcessLoops.end())
toProcessLoops.insert(it, make_pair(endOfLoop->getLabNumber(), forSt));
}
else
__spf_print(1, " Can not find end of labeled loop on line %d\n", forSt->lineNumber());
}
}
st = st->lexNext();
}
}
void ConverToEndDo(SgFile *file, vector<Messages> &messagesForFile)
{
currMessages = &messagesForFile;
getAllLabels(file);
const int funcNum = file->numberOfFunctions();
for (int i = 0; i < funcNum; ++i)
{
SgStatement *st = file->functions(i);
SgStatement *lastNode = st->lastNodeOfStmt();
vector<SgForStmt*> parentLoops;
map<SgForStmt*, SgLabel*> endOfLoops;
map<int, SgForStmt*> toProcessLoops;
fillEndOfLoop(st, endOfLoops, toProcessLoops);
for (auto &loop : toProcessLoops)
tryToConverLoop(loop.second, endOfLoops);
// convert FORALL
bool repeat = true;
while (repeat)
{
repeat = false;
vector<SgStatement*> toDel;
st = file->functions(i);
while (st != lastNode)
{
if (st->variant() == CONTAINS_STMT)
break;
if (st->variant() == FORALL_STAT || st->variant() == FORALL_NODE)
{
pair<SgStatement*, SgStatement*> newSt = convertForall(st);
checkNull(newSt.first, convertFileName(__FILE__).c_str(), __LINE__);
st->insertStmtBefore(*newSt.first, *st->controlParent());
copyLabelAndComents(st, newSt.first);
//copy for END
copyLabelAndComents(st->lastNodeOfStmt(), newSt.first->lastNodeOfStmt());
SgStatement *start = st->lexNext();
SgStatement *end = st->lastNodeOfStmt();
for (; start != end; )
{
SgStatement *copy = start->copyPtr();
if (copy->variant() == FORALL_STAT || copy->variant() == FORALL_NODE)
repeat = true;
newSt.second->lastNodeOfStmt()->insertStmtBefore(*copy, *newSt.second);
copyLabelAndComents(start, copy);
if (start->variant() != IF_NODE)
{
start = start->lastNodeOfStmt();
start = start->lexNext();
}
else
{
while (start->variant() != CONTROL_END)
start = start->lastNodeOfStmt();
start = start->lexNext();
}
}
if (st->variant() == FORALL_STAT)
{
SgStatement *copy = st->lexNext()->copyPtr();
newSt.second->lastNodeOfStmt()->insertStmtBefore(*copy, *newSt.second);
copyLabelAndComents(start, copy);
}
toDel.push_back(st);
}
st = st->lexNext();
}
for (auto &elem : toDel)
elem->deleteStmt();
}
}
}
//return <vector of decls, vector of insert>
vector<SgStatement*> createIfConditions(stack<SgExpression*> &conds, stack<SgStatement*> &ifBlocks, SgStatement *control)
{
vector<SgStatement*> ifSt = { NULL, NULL };
const int id = control->getFileId();
SgProject* proj = control->getProject();
const int line = control->lineNumber();
auto scope = getFuncStat(control);
vector<SgSymbol*> toDecls;
while (!conds.empty())
{
SgSymbol* s = NULL;
if (control->variant() == SWITCH_NODE)
{
auto nextN = checkSymbNameAndCorrect(string("spf_sc_C" + std::to_string(ifBlocks.top()->lineNumber())));
s = new SgSymbol(VARIABLE_NAME, nextN.c_str(), control->expr(0)->type(), scope);
}
else
{
auto nextN = checkSymbNameAndCorrect(string("spf_if_C" + std::to_string(ifBlocks.top()->lineNumber())));
s = new SgSymbol(VARIABLE_NAME, nextN.c_str(), SgTypeBool(), scope);
}
toDecls.push_back(s);
SgAssignStmt* check = new SgAssignStmt(*new SgVarRefExp(s), *conds.top());
check->setFileId(id);
check->setProject(proj);
check->setlineNumber(line);
if (ifSt[0])
{
if (ifSt[1])
{
ifSt[1] = new SgIfStmt(*new SgExpression(NOT_OP, new SgVarRefExp(s)), *ifSt[1]);
ifSt[1]->insertStmtAfter(*ifSt[0], *ifSt[1]);
}
else
ifSt[1] = new SgIfStmt(*new SgExpression(NOT_OP, new SgVarRefExp(s)), *ifSt[0]);
ifSt[1]->setFileId(id);
ifSt[1]->setProject(proj);
ifSt[1]->setlineNumber(line);
ifSt[0] = check;
}
else
ifSt[0] = check;
ifBlocks.top()->setExpression(0, *new SgVarRefExp(s));
ifBlocks.pop();
conds.pop();
}
makeDeclaration(scope, toDecls);
return ifSt;
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "../Utils/errors.h"
void ConverToEndDo(SgFile *file, std::vector<Messages> &messagesForFile);
std::vector<SgStatement*> createIfConditions(std::stack<SgExpression*>& conds, std::stack<SgStatement*>& ifBlocks, SgStatement *control);
struct SearchInfo
{
SgExpression *expr;
SgStatement *lastSt;
bool none;
};

View File

@@ -0,0 +1,955 @@
#include "fix_common_blocks.h"
using std::vector;
using std::map;
using std::set;
using std::string;
using std::to_string;
using std::pair;
using std::make_pair;
using std::stack;
using std::deque;
using std::reverse;
using std::tuple;
//// main function --> fixCommonBlocks
////// step1: build union for each common block
/// main function:
// renew unions for all common blocks in the file
static void BuildNewCommDecls(SgFile* file, const map<string, CommonBlock*> allCommonBlocks,
map<string, deque<CommConstraint>>& newCommonDecls, map<string, map<string, deque<CommConstraint>>>& commDecls,
set<string>& badCommon, map<string, set<string>>& notUsedVars, vector<SgStatement*>& programUnits);
// get names of variables and array elements, which were referenced in programm unit
static set<string> getUses(SgStatement* firstSt, const set<string>& commonVarNames);
static void getUsesFromExpr(SgExpression* expr, const set<string>& commonVarNames, set<string>& used);
// splits arrays into elements and replaces not used vars with empty constraints
static bool splitType(deque<CommConstraint>& d, bool check_use, const set<string>& namesOfUsedVars);
// create constraits set
static deque<CommConstraint> makeConstraints(deque<CommConstraint>& constraints, const set<string>& namesOfUsedVars, set<string>& notUsedVars);
// build union
static bool buildConstraintsUnion(deque<CommConstraint>& U, deque<CommConstraint> B, const set<string>& namesOfUsedVars, pair<CommConstraint, CommConstraint>& problemConstraints);
static bool docheckUnequalConstraints(deque<CommConstraint>& U, deque<CommConstraint>& B, deque<CommConstraint>& newU, pair<CommConstraint, CommConstraint>& problemConstraints);
static bool check(deque<CommConstraint>& A, deque<CommConstraint>& B, pair<CommConstraint, CommConstraint>& problemConstraints);
/// small help functions:
static string getParentName(const string& name);
static bool equalDims(const CommConstraint& a, const CommConstraint& b);
static bool equalConstraints(const CommConstraint& a, const CommConstraint& b);
static void addElem(deque<CommConstraint>& comm, const CommConstraint& elem);
//////
// change names of variables in 'constraints'
static void fixNames(deque<CommConstraint>& constraints, const string& commName);
////// step2: transformation
/// main function
// peform transformation on every program unit in the file
static void fixFunctions(SgFile* file, vector<SgStatement*> programUnits, map<string, deque<CommConstraint>>& newCommonDecls,
map<string, map<string, deque<CommConstraint>>>& commDecls, const set<string>& badCommon, map<string, set<string>>& notUsedVars);
// get pairs of names (namesOldToNew) for renaming
static bool getNamesOldToNew(deque<CommConstraint> newDecl, deque<CommConstraint> oldDecl, map<string, string>& namesOldToNew);
// create new symbols for new variables in new common declaration (constraints)
static void makeCommVarSymbs(const deque<CommConstraint>& constraints, SgFile* file, SgStatement* func, string commName,
map<string, SgSymbol*>& symbs, vector<SgSymbol*>& needNewDecl);
// delete from program unit all references to names in commVarNames
static void deleteOldVars(SgStatement* firstSt, const set<string>& commVarNames);
// calls fixExpression for each statement, replaces names in data statement
static void renameVariables(SgStatement* firstSt, const map<string, SgSymbol*>& newVarSymbs, const map<string, string>& namesOldToNew);
// replacing variables or array elements in expression expr if their names are in namesOldToNew
static SgExpression* fixExpression(SgExpression* expr, const map<string, SgSymbol*>& newSymbs, const map<string, string>& namesOldToNew);
// make new exprList exprssion for new declaration decl with symbols from newSymbs
static SgExpression* makeExprListForCommon(const deque<CommConstraint>& decl, const map<string, SgSymbol*>& newSymbs,
SgFile* file, SgStatement* firstSt);
// replace old common declarations with new ones
static void rewriteCommon(SgStatement* firstSt, map<string, SgExpression*>& commListExprs);
/// help functions:
static SgExpression* makeIdxFromStr(const string& str);
// make new expression of array element
static SgExpression* newArrElemExpr(const string& newName, const map<string, SgSymbol*>& newSymbs);
static bool variablePositionComp(const Variable* lhs, const Variable* rhs);
//////
CommConstraint::CommConstraint(const Variable* var, bool u, const string& funcName, const string& fileName)
{
used = u;
for (const auto& use : var->getAllUse())
{
if (use.getFunctionName() == funcName)
{
SgSymbol* symb = use.getUseS();
identifier = symb->identifier();
DeclInfo dInfo = DeclInfo(identifier, fileName, use.getDeclaratedPlace()->lineNumber());
uses.push_back(dInfo);
if ((symb->attributes() & DATA_BIT) != 0)
used = true;
type = symb->type();
typeVariant = type->variant();
vector<SgStatement*> decls;
declaratedInStmt(symb, &decls, false);
Distribution::Array* arr = NULL;
for (auto decl : decls)
{
arr = getArrayFromDeclarated(decl, identifier);
// TODO: for arrays located in the same place in common, with the same names, the same structure will be given,
// even if they have DIFFERENT dimensions (should be different structures)
if (arr != NULL)
break;
}
if (arr != NULL)
{
arrayInfo = arr;
size = arr->GetTypeSize();
for (auto x : arr->GetSizes())
size *= x.second - x.first + 1;
SgArrayType* arrType = isSgArrayType(type);
if (arrType != NULL)
typeVariant = arrType->baseType()->variant();
else
__spf_print(1, "! array with no array type!\n");
}
else
size = getSizeOfType(type);
}
}
}
CommConstraint::CommConstraint(const string& name, SgType* t, bool u) : used(u), type(t), identifier(name)
{
typeVariant = type->variant();
size = getSizeOfType(type);
}
CommConstraint::CommConstraint(const string& name, SgType* t, bool u, vector<DeclInfo>& us) : used(u), type(t), identifier(name), uses(us)
{
typeVariant = type->variant();
size = getSizeOfType(type);
}
string getParentName(const string& name)
{
size_t len = name.find("%");
size_t posB = name.find("(");
if (len == string::npos)
if (posB == string::npos)
return name;
else
len = posB;
else if (posB != string::npos && posB < len)
len = posB;
return name.substr(0, len);
}
void getUsesFromExpr(SgExpression* expr, const set<string>& commonVarNames, set<string>& used)
{
if (expr == NULL)
return;
if (expr->variant() == VAR_REF || expr->variant() == ARRAY_REF)
{
string name = expr->symbol()->identifier();
if (commonVarNames.find(getParentName(name)) != commonVarNames.end())
{
if (expr->variant() == VAR_REF)
used.insert(name);
else if (expr->variant() == ARRAY_REF)
{
SgArrayRefExp* arrExpr = (SgArrayRefExp*)expr;
if (arrExpr->lhs() == NULL)
used.insert(name);
else // it's array element
{
SgExpression* exprList = arrExpr->lhs();
bool ok = true;
int x;
while (exprList != NULL && ok) // TODO: evaluate indexes of elements if they are written using loop variable
{
if (-1 == CalculateInteger(exprList->lhs(), x))
ok = false;
exprList = exprList->rhs();
}
if (ok)
used.insert(expr->sunparse());
else
used.insert(name);
}
}
}
}
getUsesFromExpr(expr->lhs(), commonVarNames, used);
getUsesFromExpr(expr->rhs(), commonVarNames, used);
}
set<string> getUses(SgStatement* firstSt, const set<string>& commonVarNames)
{
set<string> used;
SgStatement* lastSt = firstSt->lastNodeOfStmt();
for (SgStatement* curSt = firstSt; curSt != lastSt; curSt = curSt->lexNext())
{
int var = curSt->variant();
if (var != COMM_STAT && var != VAR_DECL && var != VAR_DECL_90 && var != DIM_STAT) //
{
for (int i = 0; i < 3; i++)
if (curSt->expr(i) != NULL)
getUsesFromExpr(curSt->expr(i), commonVarNames, used);
}
}
return used;
}
bool equalDims(const CommConstraint& a, const CommConstraint& b)
{
const vector<pair<int, int>>& adim = a.arrayInfo->GetSizes();
const vector<pair<int, int>>& bdim = b.arrayInfo->GetSizes();
if (adim.size() != bdim.size())
return false;
for (int i = 0; i < adim.size(); i++)
{
if (adim[i].second - adim[i].first != bdim[i].second - bdim[i].first)
return false;
}
}
// TODO: add attributes to CommConstraints, check if a and b have equal attributes
bool equalConstraints(const CommConstraint& a, const CommConstraint& b)
{
if ((a.arrayInfo != NULL && b.arrayInfo == NULL) || ((a.arrayInfo == NULL && b.arrayInfo != NULL)))
return false;
if (a.typeVariant != b.typeVariant || a.size != b.size)
return false;
if (a.arrayInfo != NULL)
return a.arrayInfo->GetTypeSize() == b.arrayInfo->GetTypeSize() && equalDims(a, b);
return true;
}
void addElem(deque<CommConstraint>& comm, const CommConstraint& elem)
{
if (elem.typeVariant == 0 && !comm.empty() && comm.back().typeVariant == 0)
comm.back().size += elem.size;
else
comm.push_back(elem);
}
// TODO: check attributes: do not split arrays with pointer or target attributes if check_use == true
bool splitType(deque<CommConstraint>& d, bool check_use, const set<string>& namesOfUsedVars = {})
{
CommConstraint var = d.front();
string name = var.identifier;
if (var.typeVariant == 0 || (check_use && var.used))
return false;
if (var.arrayInfo != NULL) // TODO: arrays can be split not only into individual elements, but also into smaller arrays
{
d.pop_front();
const auto dims = var.arrayInfo->GetSizes();
int numOfDims = dims.size();
SgType* elemType = new SgType(var.typeVariant);
int elemNum = var.size / var.arrayInfo->GetTypeSize();
for (int k = elemNum - 1; k >= 0; k--)
{
string newName = name + "(";
int ind = k;
for (int i = 0; i < numOfDims; i++)
{
auto d = dims[i];
int dimLen = d.second - d.first + 1;
newName += to_string(ind % dimLen + d.first);
if (i < numOfDims - 1)
newName += ",";
ind = ind / dimLen;
}
newName += ")";
CommConstraint newVar = CommConstraint(newName, elemType, var.used, var.uses);
if (check_use && !newVar.used && namesOfUsedVars.find(newName) != namesOfUsedVars.end())
newVar.used = true;
d.push_front(newVar);
}
return true;
}
else
{
if (check_use && (var.used == false))
{
d.pop_front();
CommConstraint newVar = CommConstraint(var.identifier, var.size);
d.push_front(newVar);
return true;
}
else
return false;
}
}
deque<CommConstraint> makeConstraints(deque<CommConstraint>& constraints, const set<string>& namesOfUsedVars, set<string>& notUsedVars)
{
deque<CommConstraint> res;
while (!constraints.empty())
{
string curName = constraints.front().identifier;
if (!splitType(constraints, true, namesOfUsedVars))
{
addElem(res, constraints.front());
constraints.pop_front();
}
else
notUsedVars.insert(curName);
}
return res;
}
bool check(deque<CommConstraint>& A, deque<CommConstraint>& B, pair<CommConstraint, CommConstraint>& problemConstraints)
{
while (!A.empty() && !B.empty())
{
if (B.front().size > A.front().size)
{
if (!splitType(B, false))
{
problemConstraints.second = A.front();
return false;
}
}
else if (B.front().size < A.front().size)
{
if (A.front().typeVariant == 0)
{
A.front().size -= B.front().size;
B.pop_front();
}
else
{
problemConstraints.second = A.front();
return false;
}
}
else
{
if (A.front().typeVariant != 0 && B.front().typeVariant != 0 && !equalConstraints(A.front(), B.front()))
{
problemConstraints.second = A.front();
return false;
}
B.pop_front();
A.pop_front();
}
}
return true;
}
bool docheckUnequalConstraints(deque<CommConstraint>& U, deque<CommConstraint>& B, deque<CommConstraint>& newU, pair<CommConstraint, CommConstraint>& problemConstraints)
{
if (U.front().typeVariant == 0)
{
addElem(newU, B.front());
U.front().size -= B.front().size;
B.pop_front();
}
else
{
deque<CommConstraint> temp;
temp.push_front(U.front());
if (!check(B, temp, problemConstraints))
{
problemConstraints.first = U.front();
return false;
}
addElem(newU, U.front());
U.pop_front();
}
return true;
}
bool buildConstraintsUnion(deque<CommConstraint>& U, deque<CommConstraint> B, const set<string>& namesOfUsedVars, pair<CommConstraint, CommConstraint>& problemConstraints)
{
deque<CommConstraint> newU;
while (!U.empty() && !B.empty())
{
if (U.front().size < B.front().size)
{
if (!docheckUnequalConstraints(B, U, newU, problemConstraints))
return false;
}
else if (U.front().size > B.front().size)
{
if (!docheckUnequalConstraints(U, B, newU, problemConstraints))
return false;
}
else
{
if (U.front().typeVariant == 0 || B.front().typeVariant == 0
|| equalConstraints(U.front(), B.front()))
{
if (U.front().typeVariant == 0)
addElem(newU, B.front());
else if (B.front().typeVariant == 0)
addElem(newU, U.front());
else
{
U.front().uses.insert(U.front().uses.end(), B.front().uses.begin(), B.front().uses.end()); // adding to funcs
addElem(newU, U.front());
}
U.pop_front();
B.pop_front();
}
else
{
problemConstraints = make_pair(B.front(), U.front());
return false;
}
}
}
while (!B.empty())
{
addElem(newU, B.front());
B.pop_front();
}
while (!U.empty())
{
addElem(newU, U.front());
U.pop_front();
}
if (!newU.empty() && newU.back().typeVariant == 0)
newU.pop_back();
U = newU;
return true;
}
bool getNamesOldToNew(deque<CommConstraint> newDecl, deque<CommConstraint> oldDecl, map<string, string>& namesOldToNew)
{
bool needChange = false;
map<string, string> rename;
while (!oldDecl.empty() && !newDecl.empty())
{
if (newDecl.front().typeVariant == 0) // => oldDecl.front().typeVariant == 0
{
if (oldDecl.front().size > newDecl.front().size)
{
oldDecl.front().size -= newDecl.front().size;
needChange = true;
}
else
oldDecl.pop_front();
newDecl.pop_front();
}
else if (newDecl.front().size > oldDecl.front().size)
{
needChange = true;
deque<CommConstraint> tmp;
tmp.push_front(newDecl.front());
splitType(tmp, false);
while (!tmp.empty() && !oldDecl.empty())
{
if (oldDecl.front().typeVariant == 0)
{
if (oldDecl.front().size > tmp.front().size)
oldDecl.front().size -= tmp.front().size;
else
oldDecl.pop_front();
}
else
{
rename[oldDecl.front().identifier] = tmp.front().identifier;
oldDecl.pop_front();
}
tmp.pop_front();
}
newDecl.pop_front();
}
else if (oldDecl.front().size > newDecl.front().size) // => oldDecl.front().typeVariant == 0
{
needChange = true;
oldDecl.front().size -= newDecl.front().size;
newDecl.pop_front();
}
else // == and newDecl.front().typeVariant != 0
{
if (oldDecl.front().typeVariant == 0)
needChange = true;
else
{
if (oldDecl.front().identifier.find('(') != string::npos)
{
needChange = true;
rename[oldDecl.front().identifier] = newDecl.front().identifier;
}
else
rename[oldDecl.front().identifier] = newDecl.front().identifier;
}
oldDecl.pop_front();
newDecl.pop_front();
}
}
if (!oldDecl.empty() || !newDecl.empty())
needChange = true;
if (needChange)
namesOldToNew.insert(rename.begin(), rename.end());
return needChange;
}
void makeCommVarSymbs(const deque<CommConstraint>& constraints, SgFile* file, SgStatement* func, string commName,
map<string, SgSymbol*>& symbs, vector<SgSymbol*>& needNewDecl)
{
for (const CommConstraint& var : constraints)
{
if (var.typeVariant != 0)
{
SgSymbol* symb = findSymbolOrCreate(file, var.identifier, var.type->copyPtr(), func);
symbs[var.identifier] = symb;
needNewDecl.push_back(symb);
}
}
}
void deleteOldVars(SgStatement* firstSt, const set<string>& commVarNames)
{
SgStatement* lastSt = firstSt->lastNodeOfStmt();
vector<SgStatement*> stmtsToDelete;
for (SgStatement* curSt = firstSt; curSt != lastSt; curSt = curSt->lexNext())
{
if (curSt->variant() == VAR_DECL || curSt->variant() == VAR_DECL_90)
{
SgVarDeclStmt* varDeclSt = (SgVarDeclStmt*)curSt;
vector<SgExpression*> varsToDelete;
for (int i = 0; i < varDeclSt->numberOfVars(); i++)
{
SgExpression* var = varDeclSt->var(i);
string varName = "";
if (var->variant() == ASSGN_OP)
varName = var->lhs()->symbol()->identifier();
else
varName = var->symbol()->identifier();
if (commVarNames.find(varName) != commVarNames.end())
varsToDelete.push_back(var);
}
if (varDeclSt->numberOfVars() == varsToDelete.size())
stmtsToDelete.push_back(curSt);
else
for (SgExpression* var : varsToDelete)
varDeclSt->deleteTheVar(*var);
}
else if (curSt->variant() == DIM_STAT)
{
SgExpression* ex = curSt->expr(0);
bool first = true;
vector<SgExpression*> leftExprs;
while (ex != NULL)
{
string name = ex->lhs()->symbol()->identifier();
if (commVarNames.find(name) == commVarNames.end())
leftExprs.push_back(ex->lhs());
ex = ex->rhs();
}
if (leftExprs.empty())
stmtsToDelete.push_back(curSt);
else
curSt->setExpression(0, makeExprList(leftExprs));
}
// TODO: delete common variables form attributes statements (like DIM_STAT)
}
for (SgStatement* st : stmtsToDelete)
st->deleteStmt();
}
SgExpression* makeIdxFromStr(const string& str)
{
vector<SgExpression*> items;
int num = 0;
for (char c : str)
{
if ('0' <= c && c <= '9')
num = num * 10 + (c - '0');
else if (c == ',' || c == ')')
{
SgExpression* ex = new SgValueExp(num);
items.push_back(ex);
num = 0;
}
}
reverse(items.begin(), items.end());
SgExpression* exprList = makeExprList(items, false);
return exprList;
}
SgExpression* newArrElemExpr(const string& newName, const map<string, SgSymbol*>& newSymbs)
{
size_t pos = newName.find('(');
SgExpression* newExpr = new SgArrayRefExp(*newSymbs.at(newName.substr(0, pos)));
newExpr->setLhs(makeIdxFromStr(newName.substr(pos)));
return newExpr;
}
SgExpression* fixExpression(SgExpression* expr, const map<string, SgSymbol*>& newSymbs, const map<string, string>& namesOldToNew)
{
if (expr == NULL)
return NULL;
if (expr->variant() == VAR_REF || expr->variant() == ARRAY_REF)
{
string name = expr->symbol()->identifier();
auto nameIt = namesOldToNew.find(name);
if (nameIt != namesOldToNew.end())
{
string newName = nameIt->second;
auto symbIt = newSymbs.find(newName);
if (symbIt == newSymbs.end()) // variable -> array element
return newArrElemExpr(newName, newSymbs);
else // variable -> variable or array name -> array name
{
SgSymbol* newSymb = symbIt->second;
expr->setSymbol(newSymb);
}
}
else
{
string fullName = expr->sunparse();
auto fullNameIt = namesOldToNew.find(fullName);
if (fullNameIt != namesOldToNew.end())
{
string newName = fullNameIt->second;
auto symbIt = newSymbs.find(newName);
if (symbIt == newSymbs.end()) // array element -> array element
return newArrElemExpr(newName, newSymbs);
else // array element -> variable
{
SgVariableSymb* varSymb = (SgVariableSymb*)symbIt->second;
SgExpression* newExpr = new SgVarRefExp(*varSymb);
return newExpr;
}
}
}
}
SgExpression* lhs = fixExpression(expr->lhs(), newSymbs, namesOldToNew);
if (lhs != NULL)
expr->setLhs(lhs);
SgExpression* rhs = fixExpression(expr->rhs(), newSymbs, namesOldToNew);
if (rhs != NULL)
expr->setRhs(rhs);
return NULL;
}
void renameVariables(SgStatement* firstSt, const map<string, SgSymbol*>& newVarSymbs, const map<string, string>& namesOldToNew)
{
SgStatement* lastSt = firstSt->lastNodeOfStmt();
for (SgStatement* curSt = firstSt; curSt != NULL && curSt != lastSt; curSt = curSt->lexNext())
{
if (curSt->variant() == DATA_DECL)
{
SgValueExp* dataExpr = (SgValueExp*)curSt->expr(0);
map<string, string> data = splitData({ dataExpr });
string newDataStr = "data ";
bool needChange = false;
int left = data.size();
for (pair<const string, string>& item : data)
{
auto nameIt = namesOldToNew.find(item.first);
if (nameIt != namesOldToNew.end())
{
newDataStr += nameIt->second + "/" + item.second + "/";
needChange = true;
}
else
newDataStr += item.first + "/" + item.second + "/";
left--;
if (left != 0)
newDataStr += ", ";
}
if (needChange)
{
SgExpression* es = new SgExpression(STMT_STR);
char* value = (char*)malloc(newDataStr.size() + 1);
value[newDataStr.size()] = '\0';
memcpy(value, newDataStr.c_str(), sizeof(char) * newDataStr.size());
es->thellnd->entry.string_val = value;
curSt->setExpression(0, es);
}
}
else if (isSgExecutableStatement(curSt) || curSt->variant() == EQUI_STAT)
{
for (int i = 0; i < 3; i++)
{
SgExpression* expr = fixExpression(curSt->expr(i), newVarSymbs, namesOldToNew);
if (expr != NULL)
curSt->setExpression(i, expr);
}
}
}
}
SgExpression* makeExprListForCommon(const deque<CommConstraint>& decl, const map<string, SgSymbol*>& newSymbs,
SgFile* file, SgStatement* firstSt)
{
vector<SgExpression*> items;
for (auto it = decl.rbegin(); it != decl.rend(); it++)
{
if (it->typeVariant == 0)
continue;
SgSymbol* symb = NULL;
bool old = false;
auto symbIt = newSymbs.find(it->identifier);
if (symbIt != newSymbs.end())
symb = symbIt->second;
else
{
symb = findSymbolOrCreate(file, it->identifier, it->type, firstSt);
old = true;
}
SgVariableSymb* varSymb = isSgVariableSymb(symb);
if (varSymb->type()->variant() == T_ARRAY)
{
SgExpression* newExpr = new SgArrayRefExp(*varSymb);
items.push_back(newExpr);
}
else
{
SgExpression* newExpr = new SgVarRefExp(symb);
items.push_back(newExpr);
}
}
SgExpression* exprList = makeExprList(items, false);
return exprList;
}
void rewriteCommon(SgStatement* firstSt, map<string, SgExpression*>& commListExprs)
{
vector<SgStatement*> commonStmtsToDelete;
for (SgStatement* st = firstSt; st != firstSt->lastDeclaration()->lexNext(); st = st->lexNext())
{
if (st->variant() == COMM_STAT)
{
SgExpression* ex = st->expr(0);
bool first = true;
SgExpression* prev = NULL;
while (ex != NULL)
{
string commName = "";
SgSymbol* s = ex->symbol();
if (s == NULL)
commName = "spf_unnamed";
else
commName = s->identifier();
auto commIt = commListExprs.find(commName);
if (commIt != commListExprs.end())
{
if (commIt->second != NULL)
{
ex->setLhs(commIt->second);
commIt->second = NULL;
if (first)
first = false;
prev = ex;
ex = ex->rhs();
}
else
{
if (first)
{
st->setExpression(0, ex->rhs());
ex = st->expr(0);
}
else
{
prev->setRhs(ex->rhs());
ex = prev->rhs();
}
}
}
else
ex = ex->rhs();
}
if (st->expr(0) == NULL)
commonStmtsToDelete.push_back(st);
}
}
for (SgStatement* st : commonStmtsToDelete)
st->deleteStmt();
}
void fixNames(deque<CommConstraint>& constraints, const string& commName)
{
for (auto& var : constraints)
{
for (char& c : var.identifier)
{
if (c == ')' || c == '(')
c = 'l';
if (c == ',')
c = '_';
}
var.identifier = commName + "_" + var.identifier;
}
}
bool variablePositionComp(const Variable* lhs, const Variable* rhs)
{
return lhs->getPosition() < rhs->getPosition();
}
void fixFunctions(SgFile* file, vector<SgStatement*> programUnits, map<string, deque<CommConstraint>>& newCommonDecls,
map<string, map<string, deque<CommConstraint>>>& commDecls, const set<string>& badCommon, map<string, set<string>>& notUsedVars)
{
for (SgStatement* unitSt : programUnits)
{
string funcName = unitSt->symbol()->identifier();
if (commDecls.find(funcName) == commDecls.end())
continue;
SgStatement* firstSt = unitSt;
map<string, SgExpression*> commListExprs;
map<string, SgSymbol*> newVarSymbs; // new symbols for new variables
map<string, string> namesOldToNew; // for ranaming: old name -> new name
vector<SgSymbol*> needNewDecl;
for (auto& common : commDecls[funcName])
{
string commName = common.first;
if (badCommon.find(commName) != badCommon.end())
continue;
const deque<CommConstraint>& newDecl = newCommonDecls.at(commName);
vector<CommConstraint> varsNeedNewSymb;
bool needChange = getNamesOldToNew(newDecl, common.second, namesOldToNew);
if (!needChange)
continue;
makeCommVarSymbs(newDecl, file, firstSt, commName, newVarSymbs, needNewDecl);
commListExprs[commName] = makeExprListForCommon(newDecl, newVarSymbs, file, firstSt);
}
if (!commListExprs.empty())
{
for (const auto& item : commListExprs)
for (const auto& x : commDecls[funcName][item.first])
notUsedVars[funcName].insert(x.identifier);
deleteOldVars(unitSt, notUsedVars[funcName]);
renameVariables(unitSt, newVarSymbs, namesOldToNew);
makeDeclaration(needNewDecl, unitSt);
rewriteCommon(firstSt, commListExprs);
}
}
}
void BuildNewCommDecls(SgFile* file, const map<string, CommonBlock*> allCommonBlocks,
map<string, deque<CommConstraint>>& newCommonDecls, map<string, map<string, deque<CommConstraint>>>& commDecls,
set<string>& badCommon, map<string, set<string>>& notUsedVars, vector<SgStatement*>& programUnits)
{
string fileName = file->filename();
SgStatement* curSt = file->firstStatement();
while (curSt != NULL)
{
if (curSt->variant() == PROG_HEDR || curSt->variant() == PROC_HEDR || curSt->variant() == FUNC_HEDR || curSt->variant() == BLOCK_DATA || curSt->variant() == MODULE_STMT)
{
programUnits.push_back(curSt);
string funcName = curSt->symbol()->identifier();
for (auto item : allCommonBlocks)
{
string commName = item.first;
if (badCommon.find(commName) != badCommon.end())
continue;
CommonBlock* commonBlock = item.second;
vector<const Variable*> vars = commonBlock->getVariables(fileName, funcName);
if (vars.size() == 0)
continue;
sort(vars.begin(), vars.end(), variablePositionComp);
set<string> varNames;
for (const Variable* var : vars)
varNames.insert(var->getName());
set<string> namesOfUsedVars = getUses(curSt, varNames);
bool hasChar = false;
bool hasNotChar = false;
deque<CommConstraint> constraints;
for (const Variable* var : vars)
{
CommConstraint newConstr = CommConstraint(var, false, funcName, fileName);
if (newConstr.typeVariant == T_STRING || newConstr.typeVariant == T_ARRAY) // ignore common blocks with strings
hasChar = true;
else
hasNotChar = true;
if (namesOfUsedVars.find(newConstr.identifier) != namesOfUsedVars.end())
newConstr.used = true;
constraints.push_back(newConstr);
}
if (hasChar && hasNotChar) // TDOO: make proper warning message or separate such common blocks
__spf_print(1, "common block '%s' ('%s':%d) contains variables of symbolic and numeric types. It is required to divide\n", commName.c_str(), fileName.c_str(), constraints.back().uses.back().lineNum);
if (hasChar)
{
badCommon.insert(commName);
continue;
}
deque<CommConstraint> curComm = makeConstraints(constraints, namesOfUsedVars, notUsedVars[funcName]);
commDecls[funcName][commName] = curComm;
bool res;
pair<CommConstraint, CommConstraint> problemConstraints;
res = buildConstraintsUnion(newCommonDecls[commName], curComm, namesOfUsedVars, problemConstraints);
if (!res)
{
badCommon.insert(commName);
for (auto x : problemConstraints.first.uses) // TODO: make proper warning message
for (auto y : problemConstraints.second.uses)
__spf_print(1, "variables '%s' and '%s' in one storage association (common block '%s') have different types (files - %s:%d and %s:%d)\n",
x.varName.c_str(), y.varName.c_str(), commName.c_str(), x.fileName.c_str(), x.lineNum, y.fileName.c_str(), y.lineNum);
}
}
curSt = curSt->lastNodeOfStmt();
}
else
curSt = curSt->lexNext();
}
}
// main function
void fixCommonBlocks(const map<string, vector<FuncInfo*>> allFuncInfo, const map<string, CommonBlock*> allCommonBlocks, SgProject* project) // TODO: separate into 2 steps?
{
int filesNum = project->numberOfFiles();
map<string, map<string, map<string, deque<CommConstraint>>>> commDecls; // file_name -> function_name -> common block name -> old declaration of common block
map<string, deque<CommConstraint>> newCommonDecls; // name of common block -> cur builded declaration
map<string, set<string>> notUsedVars;
map<string, vector<SgStatement*>> programUnitsInFile;
set<string> badCommon;
for (int i = 0; i < filesNum; i++) // first step
{
SgFile* file = &project->file(i);
string fileName = file->filename();
file->switchToFile(fileName);
BuildNewCommDecls(file, allCommonBlocks, newCommonDecls, commDecls[fileName], badCommon, notUsedVars, programUnitsInFile[fileName]);
}
for (auto& elem : newCommonDecls)
fixNames(elem.second, elem.first);
for (int i = 0; i < filesNum; i++) // second step
{
SgFile* file = &project->file(i);
string fileName = file->filename();
file->switchToFile(fileName);
fixFunctions(file, programUnitsInFile[fileName], newCommonDecls, commDecls[fileName], badCommon, notUsedVars);
}
}

View File

@@ -0,0 +1,45 @@
#pragma once
#include <map>
#include <vector>
#include <set>
#include <string>
#include <tuple>
#include <algorithm>
#include "dvm.h"
#include "../Utils/SgUtils.h"
#include "../LoopAnalyzer/loop_analyzer.h"
#include "../ExpressionTransform/expr_transform.h"
struct DeclInfo // for error messages
{
std::string varName;
std::string fileName;
int lineNum;
DeclInfo() : varName(""), fileName(""), lineNum(0) {};
DeclInfo(const std::string& vn, const std::string& fn, int ln) : varName(vn), fileName(fn), lineNum(ln) {};
};
struct CommConstraint // TODO: add variable attributes
{
int size = 0;
std::string identifier;
bool used;
int typeVariant = 0;
Distribution::Array* arrayInfo = NULL;
SgType* type = NULL;
std::vector<DeclInfo> uses; // info about variables with this constraint
CommConstraint() : identifier(""), typeVariant(0), size(0), used(false) {};
CommConstraint(const std::string& name, int sz) : identifier(name), typeVariant(0), size(sz), used(false) {};
CommConstraint(const std::string& name, SgType* t, bool u);
CommConstraint(const std::string& name, SgType* t, bool u, std::vector<DeclInfo>& uses); //
CommConstraint(const Variable* var, bool u, const std::string& funcName, const std::string& fileName);
};
void fixCommonBlocks(const std::map<std::string, std::vector<FuncInfo*>> allFuncInfo, const std::map<std::string, CommonBlock*> allCommonBlocks, SgProject* project);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,16 @@
#pragma once
void insertIntrinsicStat(const std::vector<FuncInfo*>& allFuncInfo);
bool checkOutCalls(const std::set<std::string>& outCalls);
std::map<SgStatement*, std::set<std::string>> fillFromIntent(SgStatement* header);
void intentInsert(const std::vector<FuncInfo*>& allFuncInfo);
void intentInsertToInterfaces(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
void createInterfacesForAssumedSize(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
void createInterfacesForOutCalls(FuncInfo* func);
void setPureStatus(const std::set<FuncInfo*>& funcInfo);
void setPureStatus(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
void commonTransfer(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, const std::map<std::string, CommonBlock*>& commonBlocks);
void saveTransfer(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);
void moduleTransfer(const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);

View File

@@ -0,0 +1,632 @@
#include "../Utils/leak_detector.h"
#include <vector>
#include <string>
#include <set>
#include "loop_transform.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h"
#include "../SageAnalysisTool/definesValues.h"
#include "../Utils/SgUtils.h"
#include "../SageAnalysisTool/depGraph.h"
#include "../GraphCall/graph_calls_func.h"
using std::pair;
using std::map;
using std::tuple;
using std::stack;
using std::string;
using std::vector;
using std::set;
using std::make_pair;
static void buildTopParentLoop(LoopGraph *current, LoopGraph *top, map<LoopGraph*, LoopGraph*> &loopTopMap)
{
loopTopMap[current] = top;
for (int i = 0; i < current->children.size(); ++i)
buildTopParentLoop(current->children[i], top, loopTopMap);
}
static void buildLoopMap(LoopGraph *current, map<PTR_BFND, LoopGraph*> &loopMap)
{
loopMap[current->loop->thebif] = current;
for (int i = 0; i < current->children.size(); ++i)
buildLoopMap(current->children[i], loopMap);
}
void reverseCreatedNestedLoops(const string &file, vector<LoopGraph*> &loopsInFile)
{
map<PTR_BFND, LoopGraph*> loopMap;
map<LoopGraph*, LoopGraph*> loopTopMap;
for (auto &elem : loopsInFile)
{
buildLoopMap(elem, loopMap);
buildTopParentLoop(elem, elem, loopTopMap);
}
//TODO: need to rewrite
/*
auto *launches = SageTransform::LoopTransformTighten::getLaunches();
if (launches->count(file) == 0) {
__spf_print(1, " nothing to revert in %s\n", file.c_str());
return;
}
stack<pair<SgForStmt*, SageTransform::LineReorderRecord>> &backOrder = launches->at(file);
set<LoopGraph*> topLoopsToRecalaulate;
while (backOrder.size())
{
auto &elem = backOrder.top();
auto it = loopMap.find(elem.first->thebif);
if (it == loopMap.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
auto reorder = elem.second.buildReverse();
SageTransform::LineReorderer::apply(elem.first, reorder);
topLoopsToRecalaulate.insert(loopTopMap[it->second]);
backOrder.pop();
}
for (auto &elem : topLoopsToRecalaulate)
{
elem->recalculatePerfect();
elem->restoreDirective();
}*/
}
static void fillPrivateAndReductionFromComment(SgStatement *st, set<Symbol*> &privates,
map<string, set<Symbol*>> &reduction,
map<string, set<tuple<Symbol*, Symbol*, int>>> &reduction_loc)
{
for (auto &data : getAttributes<SgStatement*, SgStatement*>(st, set<int>{ SPF_ANALYSIS_DIR }))
{
fillPrivatesFromComment(new Statement(data), privates);
fillReductionsFromComment(new Statement(data), reduction);
fillReductionsFromComment(new Statement(data), reduction_loc);
}
}
static pair<SgForStmt*, depGraph*> getDepGraph(LoopGraph *loopGraph, const map<LoopGraph*, depGraph*> &depInfoForLoopGraph)
{
SgForStmt *sgForStmt = NULL;
depGraph *dg = NULL;
if (depInfoForLoopGraph.count(loopGraph) == 0)
__spf_print(1, "getDepGraph for loop at %d. No depGraph found\n", loopGraph->lineNum);
else
{
dg = depInfoForLoopGraph.at(loopGraph);
sgForStmt = isSgForStmt(dg->loop);
if (sgForStmt == NULL)
__spf_print(1, "getDepGraph for loop at %d. SgForStmt missing for depGraph\n", loopGraph->lineNum);
}
return make_pair(sgForStmt, dg);
}
static ddnature fromDepNode(depNode *node)
{
if (node->typedep == SCALARDEP || node->typedep == PRIVATEDEP)
{
ddnature nature = (ddnature) node->kinddep;
switch (nature)
{
case ddflow:
case ddanti:
case ddoutput:
return nature;
default:
break;
}
}
return dd_unknown;
}
static void displayDep(const depNode *dn)
{
SgExpression *ex1, *ex2;
int i;
ddnature nature;
ex1 = dn->varin;
ex2 = dn->varout;
if (!dn->typedep)
{
__spf_print(1, "UNKNOWN DATA DEPENDENCE\n");
return;
}
if (dn->typedep == ARRAYDEP)
{
nature = (ddnature)dn->kinddep;
__spf_print(1, "------> ");
switch (nature)
{
case ddflow:
__spf_print(1, "FLOW dependence between ");
break;
case ddanti:
__spf_print(1, "ANTI dependence between ");
break;
case ddoutput:
__spf_print(1, "OUTPUT dependence between ");
break;
case ddreduce:
__spf_print(1, "REDUCE dependence between ");
break;
}
__spf_print(1, "%s", ex1->unparse());
__spf_print(1, " (line %d) and ", dn->stmtin->lineNumber());
__spf_print(1, "%s", ex2->unparse());
__spf_print(1, " (line %d) with vector (", dn->stmtout->lineNumber());
for (i = 1; i <= dn->lenghtvect; i++)
{
if (dn->knowndist[i])
__spf_print(1, "%d", dn->distance[i]);
else
{
if (dn->distance[i] & DEPZERO)
__spf_print(1, "0");
if (dn->distance[i] & DEPGREATER)
__spf_print(1, "+");
if (dn->distance[i] & DEPLESS)
__spf_print(1, "-");
}
if (i < dn->lenghtvect)
__spf_print(1, ", ");
}
__spf_print(1, ")\n");
}
else
{
__spf_print(1, "------> ");
__spf_print(1, "This is a Scalar Dep on ");
__spf_print(1, "%s", ex1->unparse());
if (dn->typedep == PRIVATEDEP)
__spf_print(1, " and variable can be PRIVATE");
if (dn->typedep == REDUCTIONDEP)
__spf_print(1, " and variable can be REDUCTION with kind %d", dn->kinddep);
__spf_print(1, "\n");
}
}
static void printDepGraph(depGraph *dg)
{
if(dg == NULL)
return;
for (depNode *dn : dg->getNodes())
{
displayDep(dn);
/*int out = dn->stmtout != NULL ? dn->stmtout->lineNumber() : -1;
int in = dn->stmtin != NULL ? dn->stmtin->lineNumber() : -1;
__spf_print(1, "dep from %d --> %d\n", out, in);*/
}
}
static void addToMap(SgStatement *stmt, depGraph *depGraph, map<SgSymbol*, ddnature> &depMap)
{
depNode *node = NULL;
for (auto &dn : depGraph->getNodes())
{
//TODO: process ARRAYDEP!
if (dn->typedep > ARRAYDEP && dn->stmtin == stmt)
{
node = dn;
break;
}
}
if (node != NULL)
{
ddnature type = fromDepNode(node);
if (node->typedep == SCALARDEP)
type = ddoutput;
SgSymbol *symbol = node->varin->symbol();
auto it = depMap.find(symbol);
if(it != depMap.end())
depMap[symbol] = (it->second < type ? type : it->second);
else
depMap.insert(make_pair(symbol, type));
}
}
static map<SgSymbol*, ddnature> buildTransformerDependencyMap(SgForStmt *outerLoop, depGraph *outerDepGraph, SgForStmt *innerLoop, depGraph *innerDepGraph)
{
__spf_print(1, "Print outer depgraph START\n");
printDepGraph(outerDepGraph);
__spf_print(1, "Print outer depgraph END\n");
__spf_print(1, "Print inner depgraph START\n");
printDepGraph(innerDepGraph);
__spf_print(1, "Print inner depgraph END\n");
map<SgSymbol*, ddnature> depMap;
for (SgStatement *stmt = outerLoop->lexNext(); stmt != outerLoop->lastNodeOfStmt(); stmt = stmt->lexNext())
{
addToMap(stmt, innerDepGraph, depMap);
addToMap(stmt, outerDepGraph, depMap);
}
return depMap;
}
static SgForStmt* lexNextLoop(SgStatement* pStmt, SgStatement* end)
{
SgStatement* pClosestDo = pStmt;
while (!isSgForStmt(pClosestDo) && pClosestDo != end)
pClosestDo = pClosestDo->lexNext();
return isSgForStmt(pClosestDo);
}
static ddnature getOrDefault(const map<SgSymbol*, ddnature> &inMap, SgSymbol *key, ddnature defaultValue)
{
//implementation must be visible to compiler
auto it = inMap.find(key);
if (it == inMap.end())
return defaultValue;
else
return it->second;
};
static void processArgs(SgExpression *ex, set<SgSymbol*> &assignToScalars, bool &allAssignmentOrIf, int numArg, const FuncInfo *currF)
{
if (ex)
{
bool onlyIn = false;
if (currF)
if (currF->funcParams.isArgIn(numArg) && !currF->funcParams.isArgOut(numArg))
onlyIn = true;
if (ex->variant() == ARRAY_REF)
{
if (!onlyIn)
allAssignmentOrIf = false;
}
else if (ex->variant() == VAR_REF)
{
if (!onlyIn)
assignToScalars.insert(OriginalSymbol(ex->symbol()));
}
}
}
static void findfuncCalls(SgExpression *ex, set<SgSymbol*>& assignToScalars, bool& allAssignmentOrIf, const map<string, FuncInfo*>& mapFuncInfo)
{
if (ex)
{
if (ex->variant() == FUNC_CALL)
{
SgFunctionCallExp* funcExp = (SgFunctionCallExp*)ex;
const string fName = funcExp->funName()->identifier();
if (!isIntrinsicFunctionName(fName.c_str()))
{
auto itF = mapFuncInfo.find(fName);
FuncInfo* currF = NULL;
if (itF != mapFuncInfo.end())
currF = itF->second;
for (int z = 0; z < funcExp->numberOfArgs(); ++z)
processArgs(funcExp->arg(z), assignToScalars, allAssignmentOrIf, z, currF);
}
}
findfuncCalls(ex->lhs(), assignToScalars, allAssignmentOrIf, mapFuncInfo);
findfuncCalls(ex->rhs(), assignToScalars, allAssignmentOrIf, mapFuncInfo);
}
}
static bool processInterval(SgStatement* invBegin, SgStatement* invEnd, set<SgSymbol*>& assignToScalars, const map<string, FuncInfo*>& mapFuncInfo)
{
bool allAssignmentOrIf = true;
SgStatement* stmt = invBegin;
while (stmt != invEnd)
{
allAssignmentOrIf = allAssignmentOrIf && (isSgAssignStmt(stmt) || isSgIfStmt(stmt) || isSgLogIfStmt(stmt) || isSgControlEndStmt(stmt));
if (stmt->variant() == ASSIGN_STAT)
{
if (stmt->expr(0)->variant() == ARRAY_REF)
allAssignmentOrIf = false;
else
assignToScalars.insert(OriginalSymbol(stmt->expr(0)->symbol()));
}
else if (stmt->variant() == PROC_STAT)
{
if (!isIntrinsicFunctionName(stmt->symbol()->identifier()))
{
auto itF = mapFuncInfo.find(stmt->symbol()->identifier());
FuncInfo* currF = NULL;
if (itF != mapFuncInfo.end())
currF = itF->second;
int num = 0;
for (SgExpression* ex = stmt->expr(0); ex; ex = ex->rhs(), ++num)
processArgs(ex->lhs(), assignToScalars, allAssignmentOrIf, num, currF);
}
}
for (int z = 0; z < 3; ++z)
findfuncCalls(stmt->expr(z), assignToScalars, allAssignmentOrIf, mapFuncInfo);
stmt = stmt->lexNext();
}
return allAssignmentOrIf;
}
static bool validateInvariantStatement(SgStatement* invBegin, SgStatement* invEnd,
const map<SgSymbol*, ddnature> &dependencies, const map<string, FuncInfo*>& mapFuncInfo)
{
//by type check
SgStatement* stmt = invBegin;
set<SgSymbol*> assignToScalarsOuter;
set<SgSymbol*> assignToScalarsInner;
bool allAssignmentOrIf = processInterval(invBegin, invEnd, assignToScalarsOuter, mapFuncInfo);
processInterval(invEnd, invEnd->lastNodeOfStmt(), assignToScalarsInner, mapFuncInfo);
if (allAssignmentOrIf)
{
//TODO: use CFG graph for this analysis
//TODO: improve it
for (auto& elem : assignToScalarsInner)
if (assignToScalarsOuter.find(elem) != assignToScalarsOuter.end())
return false;
bool hasFlowDep = false;
stmt = invBegin;
while (stmt != invEnd && !hasFlowDep)
{
SgAssignStmt* assignStmt = isSgAssignStmt(stmt);
if(assignStmt)
{
SgSymbol* symbol = assignStmt->lhs()->symbol();
auto dependency = getOrDefault(dependencies, symbol, ddnovalue);
hasFlowDep = hasFlowDep
|| dependency == ddflow
|| dependency == dd_unknown;
}
stmt = stmt->lexNext();
}
if (hasFlowDep)
{
bool hasAntiOrOutputDep = false;
stmt = invBegin;
while (stmt != invEnd && !hasAntiOrOutputDep)
{
SgAssignStmt* assignStmt = isSgAssignStmt(stmt);
if(assignStmt)
{
SgSymbol* symbol = assignStmt->lhs()->symbol();
auto dependency = getOrDefault(dependencies, symbol, ddnovalue);
hasAntiOrOutputDep = hasAntiOrOutputDep
|| dependency == ddanti
|| dependency == ddoutput
|| dependency == dd_unknown;
}
stmt = stmt->lexNext();
}
if (!hasAntiOrOutputDep)
{
__spf_print(1, "%d : Only flow dependencies present, can tighten.\n", invBegin->lineNumber());
return true;
}
}
else
{
__spf_print(1, "%d : Invariant value not used in loop, can tighten.\n", invBegin->lineNumber());
return true;
}
}
__spf_print(1, "%d : Invariant cannot be moved into loop.\n", invBegin->lineNumber());
return false;
}
static bool canTightenSingleLevel(SgForStmt* outerLoop, const map<SgSymbol*, ddnature> &dependencies, const map<string, FuncInfo*>& mapFuncInfo)
{
SgStatement* outerEnddo = outerLoop->lastNodeOfStmt();
SgForStmt* innerLoop = lexNextLoop(outerLoop->lexNext(), outerEnddo);
if (innerLoop != NULL)
{
bool beforeValid = validateInvariantStatement(outerLoop->lexNext(), innerLoop, dependencies, mapFuncInfo);
//TODO:
//validateInvariantStatement(innerLoop->lastNodeOfStmt()->lexNext(), outerEnddo, dependencies);
bool afterValid = (outerLoop->lastNodeOfStmt() == innerLoop->lastNodeOfStmt()->lexNext());
return beforeValid && afterValid;
}
else
return false;
}
static int canTighten(SgForStmt* pForLoop, const map<SgSymbol*, ddnature> &dependencies, const map<string, FuncInfo*>& mapFuncInfo)
{
int nestDepth = 1;
SgForStmt* processedLoop = pForLoop;
while (canTightenSingleLevel(processedLoop, dependencies, mapFuncInfo))
{
processedLoop = lexNextLoop(processedLoop->lexNext(), NULL);
nestDepth++;
}
if (nestDepth == 1)
return 0;
else
return nestDepth;
}
static int canTighten(SgForStmt* pForLoop)
{
int nestnessLevel = 1;
SgForStmt* nextOuterLoop = pForLoop;
while (nextOuterLoop)
{
SgStatement* outerLoopControlEnd = nextOuterLoop->lastNodeOfStmt();
SgStatement* nextInnerLoop = nextOuterLoop->lexNext();
while (!isSgForStmt(nextInnerLoop) && nextInnerLoop != outerLoopControlEnd)
nextInnerLoop = nextInnerLoop->lexNext();
if (nextInnerLoop == outerLoopControlEnd) //no for loops found in outerloop
nextOuterLoop = NULL;
else //inner for loop found
{
nestnessLevel++;
nextOuterLoop = isSgForStmt(nextInnerLoop);
}
}
if (nestnessLevel == 1)
return 0;
else
return nestnessLevel;
}
static SgStatement* sinkIntoNextNearestLoop(SgStatement* pStmt, SgStatement* nextLoop)
{
__spf_print(1, "%d : SinkIntoNextNearestLoop\n", pStmt->lineNumber());
if(!isSgIfStmt(pStmt->controlParent()))
{
SgStatement *extr = pStmt->extractStmt();
nextLoop->insertStmtAfter(*extr, *nextLoop);
}
return pStmt;
}
static SgStatement* sinkIntoPreviousNearestLoop(SgStatement* pStmt, SgStatement* prevLoop, SgStatement* afterStmt)
{
__spf_print(1, "%d : sinkIntoPreviousNearestLoop\n", pStmt->lineNumber());
if(!isSgIfStmt(pStmt->controlParent()))
{
SgStatement *extr = pStmt->extractStmt();
afterStmt->insertStmtAfter(*extr, *prevLoop);
}
return pStmt;
}
static void tightenSingleLevel(SgForStmt* outerLoop, SgForStmt* topLevelForLoop)
{
SgForStmt* innerLoop = lexNextLoop(outerLoop->lexNext(), NULL);
{
//move statements after given loop before the inner loop
//moving these statements is done in reverse order,
// because insertion is always after the inner loop header
//begin := statement before closest inner loop header
SgStatement* begin = innerLoop->lexPrev();
SgStatement* end = outerLoop;
SgStatement* stmt = begin;
SgStatement* next;
while (stmt != end)
{
next = stmt->lexPrev();
sinkIntoNextNearestLoop(stmt, innerLoop);
stmt = next;
}
}
{
SgStatement* begin = outerLoop->lastNodeOfStmt()->lexPrev();
SgStatement* end = innerLoop->lastNodeOfStmt();
SgStatement* afterStmt = end->lexPrev();
SgStatement* stmt = begin;
SgStatement* next;
while (stmt != end)
{
next = stmt->lexPrev();
sinkIntoPreviousNearestLoop(stmt, innerLoop, afterStmt);
stmt = next;
}
}
}
static bool tighten(SgForStmt* pForLoop, int level)
{
if (level > canTighten(pForLoop))
//cannot do that
return false;
int processing = 2;
SgForStmt* processedLoop = pForLoop;
while (processing <= level)
{
tightenSingleLevel(processedLoop, pForLoop);
processedLoop = lexNextLoop(processedLoop->lexNext(), NULL);
processing++;
}
return true;
}
bool createNestedLoops(LoopGraph *current, const map<LoopGraph*, void*> &depInfoForLoopGraphV,
const map<string, FuncInfo*>& mapFuncInfo, vector<Messages> &messages)
{
map<LoopGraph*, depGraph*> depInfoForLoopGraph;
for (auto& elem : depInfoForLoopGraphV)
depInfoForLoopGraph[elem.first] = (depGraph*)elem.second;
bool wasTightened = false;
// has non nested child loop
__spf_print(1, " createNestedLoops for loop at %d. Start\n", current->lineNum);
bool outerTightened = false;
bool loopCondition = current->children.size() == 1 && current->perfectLoop == 1 && !current->hasLimitsToParallel();
if (loopCondition)
{
pair<SgForStmt*, depGraph*> outerLoopDependencies = getDepGraph(current, depInfoForLoopGraph);
pair<SgForStmt*, depGraph*> innerLoopDependencies = getDepGraph(current->children.at(0), depInfoForLoopGraph);
if (outerLoopDependencies.first && outerLoopDependencies.second && innerLoopDependencies.first && innerLoopDependencies.second)
{
SgForStmt *outerLoop = outerLoopDependencies.first;
map<SgSymbol*, ddnature> depMap = buildTransformerDependencyMap(outerLoop, outerLoopDependencies.second, innerLoopDependencies.first, innerLoopDependencies.second);
if (canTighten(outerLoop, depMap, mapFuncInfo) >= 2)
{
outerTightened = tighten(outerLoop, 2);
LoopGraph *firstChild = current->children.at(0);
if (outerTightened)
firstChild->perfectLoop = countPerfectLoopNest(firstChild->loop);
__spf_print(1, " createNestedLoops for loop at %d. Tighten success: %d\n", current->lineNum, outerTightened);
wchar_t buf[256];
std::wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"Loops on lines %d and %d were combined", current->lineNum, firstChild->lineNum);
__spf_printToLongBuf(messageR, R100, current->lineNum, firstChild->lineNum);
messages.push_back(Messages(NOTE, current->lineNum, messageR, messageE, 2005));
}
}
}
wasTightened = outerTightened;
for (int i = 0; i < current->children.size(); ++i)
{
__spf_print(1, " createNestedLoops for loop at %d. Transform child %d\n", current->lineNum, i);
bool result = createNestedLoops(current->children[i], depInfoForLoopGraphV, mapFuncInfo, messages);
wasTightened = wasTightened || result;
}
//update perfect loop
current->recalculatePerfect();
__spf_print(1, " createNestedLoops for loop at %d. End\n", current->lineNum);
return wasTightened;
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <map>
#include "../GraphLoop/graph_loops.h"
void reverseCreatedNestedLoops(const std::string &file, std::vector<LoopGraph*> &loopsInFile);
bool createNestedLoops(LoopGraph *current, const std::map<LoopGraph*, void*> &depInfoForLoopGraph,
const std::map<std::string, FuncInfo*>& mapFuncInfo, std::vector<Messages> &messages);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
#pragma once
#include "dvm.h"
#include "../GraphLoop/graph_loops.h"
#include "../SageAnalysisTool/depGraph.h"
#include "../SageAnalysisTool/OmegaForSage/include/lang-interf.h"
#include "../DirectiveProcessing/directive_parser.h"
#include <vector>
int combineLoops(SgFile *file, std::vector<LoopGraph*> &loopGraphs, std::vector<Messages> &messages,
const std::pair<std::string, int>& onPlace, const std::map<LoopGraph*, depGraph*>& depInfoForLoopGraph, int& countOfTransform);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
#pragma once
#include <vector>
#include <map>
#include "dvm.h"
#include "../GraphLoop/graph_loops.h"
#include "../SageAnalysisTool/depGraph.h"
#include "../Utils/CommonBlock.h"
int splitLoops(SgFile *file, std::vector<LoopGraph*> &loopGraphs, std::vector<Messages> &messages, const std::map<LoopGraph*, depGraph*>& depInfoForLoopGraph, const std::map<std::string, CommonBlock*>& commonBlocks, const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo, int& countOfTransform);

View File

@@ -0,0 +1,213 @@
#include "loops_unrolling.h"
#include "../LoopAnalyzer/loop_analyzer.h"
#include "../Utils/errors.h"
#include "../GraphLoop/graph_loops_func.h"
#include <string>
#include <vector>
#include <set>
using std::string;
using std::wstring;
using std::vector;
using std::set;
static void replaceSymbToValue(SgExpression* ex, const string& symb, const int value)
{
if (ex)
{
if (ex->lhs())
{
SgExpression* left = ex->lhs();
if (left->variant() == VAR_REF && OriginalSymbol(left->symbol())->identifier() == symb)
ex->setLhs(new SgValueExp(value));
}
if (ex->rhs())
{
SgExpression* right = ex->rhs();
if (right->variant() == VAR_REF && OriginalSymbol(right->symbol())->identifier() == symb)
ex->setRhs(new SgValueExp(value));
}
replaceSymbToValue(ex->lhs(), symb, value);
replaceSymbToValue(ex->rhs(), symb, value);
}
}
static bool ifHasConstruct(SgStatement* copy, vector<Messages>& messages)
{
bool onlyOne = (copy->lastNodeOfStmt() == copy);
SgStatement* last = copy->lastNodeOfStmt()->lexNext();
SgStatement* st = copy;
bool retVal = false;
do
{
if (st->variant() == IF_NODE ||
st->variant() == SWITCH_NODE ||
st->variant() == CYCLE_STMT ||
st->variant() == EXIT_STMT ||
st->variant() == CASE_NODE ||
st->variant() == DEFAULT_NODE ||
st->variant() == CONTROL_END)
{
if (BIF_SYMB(st->thebif))
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"This operator has construct-name, so it does not allowed for UNROLL transformation");
__spf_printToLongBuf(messageR, R195);
messages.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 2015));
retVal = true;
}
}
if (st->variant() == FOR_NODE)
{
if (isSgForStmt(st)->constructName())
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"This operator has construct-name, so it does not allowed for UNROLL transformation");
__spf_printToLongBuf(messageR, R195);
messages.push_back(Messages(ERROR, st->lineNumber(), messageR, messageE, 2015));
retVal = true;
}
}
if (onlyOne)
break;
st = st->lexNext();
} while (st != last);
return retVal;
}
int unrollLoops(SgFile* file, vector<LoopGraph*>& loopGraph, vector<Messages>& messages)
{
int err = 0;
for (auto& loop : loopGraph)
{
if (loop->children.size())
err += unrollLoops(NULL, loop->children, messages);
if (err > 0)
break;
auto attrsTr = getAttributes<SgStatement*, SgStatement*>(loop->loop->GetOriginal(), set<int>{ SPF_TRANSFORM_DIR });
for (auto attr : attrsTr)
{
SgExpression* list = attr->expr(0);
if (list->lhs()->variant() == SPF_UNROLL_OP)
{
int range[3] = { 0, 0, 0 };
bool inited = false;
if (list->lhs()->lhs())// if with range
{
SgExprListExp* listExp = isSgExprListExp(list->lhs()->lhs());
checkNull(listExp, convertFileName(__FILE__).c_str(), __LINE__);
int len = listExp->length();
if (len != 3)
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"wrong directive syntax");
__spf_printToLongBuf(messageR, R185);
messages.push_back(Messages(ERROR, loop->lineNum, messageR, messageE, 2015));
err = 1;
break;
}
inited = true;
bool isFalse = !listExp->elem(0)->isInteger() || !listExp->elem(1)->isInteger() || !listExp->elem(2)->isInteger();
if (!isFalse)
{
loop->startVal = listExp->elem(0)->valueInteger();
loop->endVal = listExp->elem(1)->valueInteger();
loop->stepVal = listExp->elem(2)->valueInteger();
std::tuple<int, int, int> tmp;
loop->calculatedCountOfIters = calculateLoopIters(listExp->elem(0), listExp->elem(1), listExp->elem(2), tmp);
}
else
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"wrong directive syntax - expression must be evaluated");
__spf_printToLongBuf(messageR, R186);
messages.push_back(Messages(ERROR, loop->lineNum, messageR, messageE, 2015));
err = 1;
break;
}
}
if (loop->calculatedCountOfIters == 0) // unknown
{
wstring messageE, messageR;
__spf_printToLongBuf(messageE, L"expression must be evaluated");
__spf_printToLongBuf(messageR, R187);
messages.push_back(Messages(ERROR, loop->lineNum, messageR, messageE, 2015));
err = 1;
break;
}
int unroll = loop->calculatedCountOfIters;
SgForStmt* currLoop = (SgForStmt*)loop->loop;
SgStatement* last = currLoop->lastNodeOfStmt();
const string loopS = OriginalSymbol(currLoop->symbol())->identifier();
vector<SgStatement*> orig;
SgStatement* body = currLoop->body();
while (body != last)
{
orig.push_back(body);
body = body->lastNodeOfStmt();
body = body->lexNext();
}
SgStatement* insertBefore = last->lexNext();
SgStatement* cp = insertBefore->controlParent();
for (int z = 0, val = loop->startVal; z < unroll; ++z, val += loop->stepVal)
{
for (auto& elem : orig)
{
SgStatement* copyS = elem->copyPtr();
if (ifHasConstruct(elem, messages))
err = 1;
SgStatement* lastS = copyS->lastNodeOfStmt();
if (copyS == lastS)
lastS = lastS->lexNext();
SgStatement* st = copyS;
do
{
for (int k = 0; k < 3; ++k)
replaceSymbToValue(st->expr(k), loopS, val);
st = st->lexNext();
} while (st != lastS);
insertBefore->insertStmtBefore(*copyS, *cp);
}
}
currLoop->extractStmt();
break;
}
}
}
return err;
}

View File

@@ -0,0 +1,7 @@
#pragma once
#include "dvm.h"
#include "../GraphLoop/graph_loops.h"
#include <vector>
int unrollLoops(SgFile* file, std::vector<LoopGraph*>& loopGraph, std::vector<Messages>& messages);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
#include "dvm.h"
#include "../GraphLoop/graph_loops.h"
#include <string>
#include <vector>
#include <set>
void privateArraysResizing(SgFile *file, const std::vector<LoopGraph*> &loopGraphs, std::vector<Messages> &messages, int& countOfTransform, const std::map<std::pair<std::string, int>, std::set<SgStatement*>>& usersDirectives, bool isExpand);
void analyzeShrinking(SgFile* file, const std::vector<LoopGraph*>& loopGraphs, std::vector<Messages>& messages, const std::map<std::pair<std::string, int>, std::set<SgStatement*>>& usersDirectives);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
#pragma once
#include "dvm.h"
#include "../DirectiveProcessing/directive_parser.h"
#include "../CFGraph/CFGraph.h"
#include "../CFGraph/RD_subst.h"
// Regime defines the regime of private removing
enum class Regime { DEFLT = 1, REGULAR_INDEXES };
// PrivateToRemove represents private variable of loop, that can be removed
// by substitution of its definition statements (DEF) into usage statements (USE).
// fixedDimensions is used for comparison of DEF and USE statements
struct PrivateToRemove {
LoopGraph* loop;
SgSymbol* varSymbol;
Regime regime;
std::vector<std::pair<SgAssignStmt*, SgStatement*>> defUseStmtsPairs;
std::vector<bool> fixedDimensions;
};
// removePrivates removes all privates from vector privatesToRemoveGloval
// and add info messages
void removePrivates(std::string filename, std::vector<Messages>& messages,
const std::map<std::string, CommonBlock*>& commonBlocks,
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
int& countOfTransform);
// removePrivatesAnalysis checks all private variables in loopGraphs specified by usersDirectives
// if they can be removed, and adds those that can to vector privatesToRemoveGloval.
// if private var cannot be removed, the error message is returned with vector messages
void removePrivatesAnalysis(std::string filename,
std::vector<LoopGraph*>& loopGraphs,
std::vector<Messages>& messages,
const std::map<std::pair<std::string, int>, std::set<SgStatement*>>& usersDirectives,
const std::map<std::string, CommonBlock*>& commonBlocks,
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo);

View File

@@ -0,0 +1,536 @@
#include "replace_dist_arrays_in_io.h"
#include "../ParallelizationRegions/resolve_par_reg_conflicts.h"
#include <string>
#include <map>
#include <set>
#include <ExpressionTransform/expr_transform.h>
using std::map;
using std::set;
using std::string;
using std::vector;
using std::to_string;
using std::make_pair;
using std::pair;
#define DEBUG_TRACE 0
static void findArrays(SgExpression* exp, set<SgSymbol*>& arrays)
{
if (exp)
{
if (isArrayRef(exp))
arrays.insert(exp->symbol());
findArrays(exp->lhs(), arrays);
findArrays(exp->rhs(), arrays);
}
}
static void populateDistributedIoArrays(map<SgSymbol*, set<SgStatement*>>& arrays, SgStatement* stat)
{
auto var = stat->variant();
if (var != READ_STAT && var != PRINT_STAT && var != WRITE_STAT)
return;
// check if such IO allowed in dvm:
// list should consist only of single array and format string should be *
bool need_replace = false;
SgExpression* ioList = stat->expr(0);
if (!ioList)
return;
if (ioList->variant() != EXPR_LIST)
return;
if (ioList->rhs() == NULL)
{
SgExpression* arg = ioList->lhs();
if (!arg)
return;
if (!isArrayRef(arg))
return;
if (arg->lhs())
need_replace = true;
}
else
{
need_replace = true;
}
if (!need_replace)
{
switch (var)
{
case PRINT_STAT:
{
SgExpression* fmt = stat->expr(1);
if (!fmt || fmt->variant() != SPEC_PAIR || fmt->lhs()->variant() != KEYWORD_VAL)
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return;
}
if (fmt->rhs()->variant() != KEYWORD_VAL || fmt->rhs()->sunparse() != "*")
need_replace = true;
break;
}
case READ_STAT:
case WRITE_STAT:
{
SgExpression* spec = stat->expr(1);
__spf_print(DEBUG_TRACE, "[%d: %s (%d)]\n", 2000, spec->rhs()->unparse(), spec->rhs()->variant());
if (!spec || spec->variant() != EXPR_LIST ||
spec->lhs()->variant() != SPEC_PAIR ||
!spec->rhs() || !spec->rhs()->lhs() || spec->rhs()->lhs()->variant() != SPEC_PAIR)
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return;
}
SgExpression* unit_val = spec->lhs()->rhs(), * fmt_val = spec->rhs()->lhs()->rhs();
if (unit_val->variant() != KEYWORD_VAL || unit_val->sunparse() != "*" ||
fmt_val->variant() != KEYWORD_VAL || fmt_val->sunparse() != "*")
need_replace = true;
break;
}
default:
break;
}
}
if (!need_replace)
return;
set<SgSymbol*> found_arrays;
for (int i = 0; i < 3; i++)
findArrays(stat->expr(i), found_arrays);
for (auto* by_symb : found_arrays)
{
string array_name = string(by_symb->identifier());
DIST::Array* array_p = getArrayFromDeclarated(declaratedInStmt(by_symb), array_name);
if (array_p && array_p->GetDistributeFlagVal() == Distribution::distFlag::IO_PRIV && arrays[by_symb].insert(stat).second)
__spf_print(DEBUG_TRACE, "[%d]: add array %s\n", stat->lineNumber(), array_p->GetName().c_str());
}
__spf_print(DEBUG_TRACE, "[replace]\n");
}
static void replaceArrayRec(SgSymbol* arr, SgSymbol* replace_by, SgExpression* exp, bool& has_read, bool& has_write, bool from_read, bool from_write)
{
if (!exp)
return;
if (exp->symbol() && exp->symbol()->identifier() && strcmp(exp->symbol()->identifier(), arr->identifier()) == 0)
{
has_read |= from_read;
has_write |= from_write;
exp->setSymbol(replace_by);
}
switch (exp->variant())
{
case FUNC_CALL:
{
replaceArrayRec(arr, replace_by, exp->rhs(), has_read, has_write, true, false);
replaceArrayRec(arr, replace_by, exp->lhs(), has_read, has_write, true, true);
break;
}
case EXPR_LIST:
{
replaceArrayRec(arr, replace_by, exp->lhs(), has_read, has_write, from_read, from_write);
replaceArrayRec(arr, replace_by, exp->rhs(), has_read, has_write, from_read, from_write);
break;
}
default:
{
replaceArrayRec(arr, replace_by, exp->lhs(), has_read, has_write, true, false);
replaceArrayRec(arr, replace_by, exp->rhs(), has_read, has_write, true, false);
break;
}
}
}
static void replaceArrayRec(SgSymbol* arr, SgSymbol* replace_by, SgStatement* st, bool& has_read, bool& has_write)
{
if (!st)
return;
switch (st->variant())
{
case ASSIGN_STAT:
case READ_STAT:
{
replaceArrayRec(arr, replace_by, st->expr(0), has_read, has_write, false, true);
replaceArrayRec(arr, replace_by, st->expr(1), has_read, has_write, true, false);
break;
}
case PROC_STAT:
case FUNC_STAT:
{
replaceArrayRec(arr, replace_by, st->expr(0), has_read, has_write, true, false);
replaceArrayRec(arr, replace_by, st->expr(1), has_read, has_write, true, true);
break;
}
default:
{
for (int i = 0; i < 3; i++)
replaceArrayRec(arr, replace_by, st->expr(i), has_read, has_write, true, false);
break;
}
}
}
static void copyArrayBetweenStatements(SgSymbol* replace_symb, SgSymbol* replace_by, SgStatement* start, SgStatement* last, bool start_is_scope)
{
while (start->lexNext() && !isSgExecutableStatement(start->lexNext()))
start = start->lexNext();
auto* stop = last->lexNext();
bool has_read = false, has_write = false;
for (auto* st = start->lexNext(); st && st != stop->lexPrev(); st = st->lexNext())
replaceArrayRec(replace_symb, replace_by, st, has_read, has_write);
if (has_read)
{
// A_copy = A
SgAssignStmt* assign = new SgAssignStmt(*new SgArrayRefExp(*replace_by), *new SgArrayRefExp(*replace_symb));
assign->setlineNumber(getNextNegativeLineNumber()); // before region
auto* parent = start_is_scope ? start : start->controlParent();
if (parent && parent->lastNodeOfStmt() == start)
parent = parent->controlParent();
start->insertStmtAfter(*assign, *parent);
}
if (has_write)
{
// A = A_reg
SgAssignStmt* assign = new SgAssignStmt(*new SgArrayRefExp(*replace_symb), *new SgArrayRefExp(*replace_by));
//TODO: bug with insertion
//assign->setlineNumber(getNextNegativeLineNumber()); // after region
last->insertStmtBefore(*assign, *(last->controlParent()));
}
}
static void replaceArrayInFragment(SgSymbol* replace_symb, const set<SgStatement*> usages, SgSymbol* replace_by, SgStatement* start, SgStatement* last, const string& filename)
{
while (start->lexNext() && !isSgExecutableStatement(start->lexNext()))
start = start->lexNext();
set<SgStatement*> not_opened, not_closed, copied;
for (auto* it = start; it; it = it->controlParent())
not_opened.insert(it);
for (auto* it = last; it; it = it->controlParent())
not_closed.insert(it);
for (auto* io_stmt : usages)
{
bool already_copied = false;
SgStatement* copy_scope = NULL;
for (auto* par = io_stmt; par; par = par->controlParent())
{
if (copied.find(par) != copied.end())
{
already_copied = true;
break;
}
else if (not_opened.find(par) != not_opened.end() || not_closed.find(par) != not_closed.end())
{
copy_scope = par;
break;
}
}
if (already_copied)
continue;
auto* scope_start = copy_scope, * scope_end = copy_scope->lastNodeOfStmt();
__spf_print(DEBUG_TRACE, "[scope to copy] %d\n", copy_scope->lineNumber());
if (not_opened.find(copy_scope) != not_opened.end() && start != copy_scope)
{
auto* from = start;
for (auto* st = from; st; st = st->controlParent())
{
__spf_print(DEBUG_TRACE, "[find start of parent %d] %d\n", copy_scope->lineNumber(), st->lineNumber());
if (st->controlParent() == copy_scope)
{
scope_start = st->lastNodeOfStmt() ? st->lastNodeOfStmt() : st;
break;
}
}
}
if (not_closed.find(copy_scope) != not_closed.end() && last != copy_scope)
{
for (auto* st = last; st; st = st->controlParent())
{
__spf_print(DEBUG_TRACE, "[find end of parent %d] %d\n", copy_scope->lineNumber(), st->lineNumber());
if (st->controlParent() == copy_scope)
{
scope_end = st;
break;
}
}
}
__spf_print(DEBUG_TRACE, "[copy %s] [%d, %d]\n", replace_symb->identifier(), scope_start->lineNumber(), scope_end->lineNumber());
copyArrayBetweenStatements(replace_symb, replace_by, scope_start, scope_end, copy_scope == scope_start);
copied.insert(copy_scope);
}
}
static bool ioReginBorder(SgStatement* stat, SgStatement* last_io_bound)
{
auto var = stat->variant();
static const set<int> border_stats =
{
PROC_STAT,
FUNC_STAT,
PROG_HEDR,
FUNC_HEDR,
PROC_HEDR,
FOR_NODE,
LOOP_NODE,
RETURN_NODE,
RETURN_STAT,
STOP_STAT,
STOP_NODE,
EXIT_STMT,
EXIT_NODE
};
if (border_stats.find(var) != border_stats.end())
return true;
if (last_io_bound && last_io_bound->lastNodeOfStmt() && last_io_bound->lastNodeOfStmt() == stat)
return true;
int parent_var;
if (var == CONTROL_END && border_stats.find(stat->controlParent()->variant()) != border_stats.end())
return true;
return false;
}
void replaceDistributedArraysInIO(vector<ParallelRegion*>& regions,
const map<string, vector<FuncInfo*>>& allFuncInfo,
map<string, vector<Messages>>& SPF_messages,
map<string, map<int, set<string>>>& newDeclsToInclude)
{
map<SgSymbol*, SgSymbol*> created_copies;
map<string, map<int, set<string>>> copied_syms;
for (auto& region : regions)
{
__spf_print(DEBUG_TRACE, "[%s]: enter region\n", region->GetName().c_str());
for (auto& linesByFile : region->GetAllLinesToModify())
{
const auto& filename = linesByFile.first;
if (SgFile::switchToFile(filename) < 0)
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return;
}
for (auto& lines : linesByFile.second)
{
__spf_print(DEBUG_TRACE, "[fragment] %s: %d:%d %d\n", filename.c_str(), lines.lines.first,
lines.lines.second, lines.isImplicit());
SgStatement* curr_stmt, * end;
if (lines.isImplicit())
{
curr_stmt = current_file->SgStatementAtLine(lines.lines.first);
end = current_file->SgStatementAtLine(lines.lines.second);
if (end)
end = end->lexNext();
}
else
{
curr_stmt = lines.stats.first->GetOriginal();
end = lines.stats.second->GetOriginal()->lexNext();
}
map<SgSymbol*, set<SgStatement*>> need_replace;
SgStatement* last_io_bound = NULL;
while (curr_stmt != end)
{
if (!curr_stmt)
break;
auto var = curr_stmt->variant();
if (var == PROC_HEDR || var == PROG_HEDR || var == FUNC_HEDR)
{
curr_stmt = curr_stmt->lexNext();
while (curr_stmt && !isSgExecutableStatement(curr_stmt))
{
last_io_bound = curr_stmt;
curr_stmt = curr_stmt->lexNext();
}
if (!curr_stmt)
break;
}
if (ioReginBorder(curr_stmt, last_io_bound))
{
for (const auto& by_array_to_copy : need_replace)
{
auto* array_to_copy = by_array_to_copy.first;
auto it = created_copies.find(array_to_copy);
if (it == created_copies.end())
{
string array_name = string(array_to_copy->identifier());
DIST::Array* array_p = getArrayFromDeclarated(declaratedInStmt(array_to_copy), array_name);
bool fromModule = (array_p->GetLocation().first == DIST::l_MODULE);
const string locationName = array_p->GetLocation().second;
auto place = *array_p->GetDeclInfo().begin();
string fileName = place.first;
string suffix = "_io_l";
if (fromModule)
suffix = "_io_m";
pair<SgSymbol*, SgSymbol*> copied;
copied.first = array_to_copy;
if (SgFile::switchToFile(fileName) == -1)
{
auto* func_stmt = curr_stmt->getScopeForDeclare();
SgStatement* insertPlace = NULL;
for (auto iterator = func_stmt->lexNext();
!isSgExecutableStatement(iterator) || isSPF_stat(iterator) &&
!(iterator->variant() == SPF_PARALLEL_REG_DIR || iterator->variant() == SPF_END_PARALLEL_REG_DIR);
iterator = iterator->lexNext())
{
insertPlace = iterator;
}
//NULL - no decl stats in function!
if (!insertPlace)
insertPlace = func_stmt;
auto st = insertPlace->controlParent();
if (st->variant() == GLOBAL)
st = insertPlace;
auto& copied_symb = array_to_copy->copy();
copied.second = &copied_symb;
auto new_name = string(array_to_copy->identifier()) + "_io_c";
copied_symb.changeName(new_name.c_str());
auto stat = array_to_copy->makeVarDeclStmt();
auto res = CalculateInteger(stat->expr(0)->copyPtr());
res->lhs()->setSymbol(copied_symb);
stat->setExpression(0, res);
insertPlace->insertStmtAfter(*stat, *st);
}
else
{
copied = copyArray(place, array_p, linesByFile.second, suffix + to_string(region->GetId()), fileName, newDeclsToInclude, copied_syms);
}
SgStatement* decl = SgStatement::getStatementByFileAndLine(place.first, place.second);
if (decl)
decl = decl->lexNext();
if (decl)
{
string dir_str;
if (decl->comments())
{
string str_comment = string(decl->comments());
if (str_comment.size() && str_comment.back() != '\n')
dir_str += "\n";
}
dir_str += "!$SPF ANALYSIS(PROCESS_PRIVATE(" + string(copied.second->identifier()) + "))\n";
decl->addComment(dir_str.c_str());
}
created_copies.insert({ array_to_copy, copied.second });
}
}
if (last_io_bound)
{
__spf_print(DEBUG_TRACE, "[io region] [%d, %d]\n", last_io_bound->lineNumber(), curr_stmt->lineNumber());
for (const auto& p : need_replace)
{
auto it = created_copies.find(p.first);
if (it != created_copies.end())
replaceArrayInFragment(p.first, p.second, it->second, last_io_bound, curr_stmt, filename);
else
{
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
return;
}
}
}
need_replace.clear();
last_io_bound = curr_stmt;
}
__spf_print(DEBUG_TRACE, "[line] %d (%d)\n", curr_stmt->lineNumber(), curr_stmt->variant());
for (int i = 0; i < 3; i++)
{
if (curr_stmt->expr(i))
{
__spf_print(DEBUG_TRACE, "[%d: %s (%d)]\n", i, curr_stmt->expr(i)->unparse(), curr_stmt->expr(i)->variant());
}
}
populateDistributedIoArrays(need_replace, curr_stmt);
curr_stmt = curr_stmt->lexNext();
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "../ParallelizationRegions/ParRegions.h"
#include "../Utils/SgUtils.h"
#include "../Utils/errors.h"
#include "../GraphCall/graph_calls.h"
void replaceDistributedArraysInIO(std::vector<ParallelRegion*>& regions,
const std::map<std::string, std::vector<FuncInfo*>>& allFuncInfo,
std::map<std::string, std::vector<Messages>>& SPF_messages,
std::map<std::string, std::map<int, std::set<std::string>>>& newDeclsToInclude);

View File

@@ -0,0 +1,382 @@
#include "../Utils/leak_detector.h"
#include <string>
#include <map>
#include "Utils/SgUtils.h"
#include "set_implicit_none.h"
using std::vector;
using std::map;
using std::set;
using std::string;
static const char commonIntLetters[6] = { 'i', 'j', 'k', 'm', 'n', 'l' };
static void InitTypes(map<char, SgType*>& types)
{
for (char letter = 'a'; letter <= 'z'; letter++)
types[letter] = 0;
}
static void FillCommonTypes(map<char, SgType*>& types)
{
for (char letter : commonIntLetters)
if (types[letter] == 0)
types[letter] = new SgType(T_INT);
for (auto letter : types)
if (letter.second == NULL)
types[letter.first] = new SgType(T_FLOAT);
}
static bool isByUse(SgSymbol* s, SgStatement* checkScope)
{
auto scope = s->scope();
auto isByUse_s = IS_BY_USE(s);
if (!isByUse_s && scope == checkScope)
return false;
else
return true;
}
static void FindAllVars(SgExpression* expr, set<SgSymbol*>& allVars, set<SgSymbol*>& allVarsConst, SgStatement* scope)
{
if (expr == NULL)
return;
const int var = expr->variant();
if (var == VAR_REF || var == ARRAY_REF || var == FUNC_CALL)
{
auto s = expr->symbol();
const string ident(s->identifier());
const int s_var = s->variant();
if (var == FUNC_CALL /*(s->attributes() & EXTERNAL_BIT)*/)
{
if (!IS_BY_USE(s) && ident.find("::") == string::npos /* && s->scope() == scope*/)
allVars.insert(s);
}
else if (s_var != CONSTRUCT_NAME ||
s_var == VARIABLE_NAME)
{
if (!IS_BY_USE(s) && ident.find("::") == string::npos && s->scope() == scope)
allVars.insert(s);
}
}
else if (var == CONST_REF)
{
auto s = expr->symbol();
if (!isByUse(s, scope))
allVarsConst.insert(s);
}
FindAllVars(expr->lhs(), allVars, allVarsConst, scope);
FindAllVars(expr->rhs(), allVars, allVarsConst, scope);
}
static char getValue(SgExpression* ex)
{
char charVal = 0;
if (ex && ex->variant() == CHAR_VAL)
charVal = isSgValueExp(ex)->charValue();
return charVal;
}
static void AddLettersToMap(SgExpression* expr, SgType* type, map<char, SgType*>& types)
{
while (expr)
{
if (expr->variant() != EXPR_LIST)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
SgExpression* val = expr->lhs();
if (val->variant() == DDOT)
{
char leftVal = getValue(val->lhs());
char rightVal = getValue(val->rhs());
if (leftVal == 0 || rightVal == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (char letter = leftVal; letter <= rightVal; letter++)
types[letter] = type;
}
else
{
char charVal = getValue(val);
if (charVal == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
types[charVal] = type;
}
expr = expr->rhs();
}
}
static vector<SgSymbol*> getVars(const set<string>& functionSymbs, set<SgSymbol*>& toRename,
const set<SgSymbol*>& allVars, const map<char, SgType*>& types,
SgStatement* scope)
{
vector<SgSymbol*> varsWithoutDecl;
map<string, SgSymbol*> vars;
for (auto& var : allVars)
{
if (vars.find(var->identifier()) != vars.end())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
vars[var->identifier()] = var;
}
for (auto& var : allVars)
{
if (functionSymbs.count(var->identifier()))
continue;
vector<SgStatement*> allDecls;
declaratedInStmt(var, &allDecls, false, (var->variant() == FUNCTION_NAME) ? scope : NULL);
bool hasTypeDecls = false;
for (auto& decl : allDecls)
{
const int var = decl->variant();
if (var == VAR_DECL || var == VAR_DECL_90 || var == STRUCT_DECL)
hasTypeDecls = true;
}
if (!hasTypeDecls)
{
const char c = var->identifier()[0];
auto it = types.find(c);
if (it != types.end())
{
var->setType(it->second);
auto s = it->second->symbol();
if (s)
{
auto itS = vars.find(s->identifier());
if (itS != vars.end())
toRename.insert(itS->second);
}
}
varsWithoutDecl.push_back(var);
}
}
return varsWithoutDecl;
}
static map<char, SgType*> FunctionImplicitCheck(SgStatement* function, const map<SgStatement*, map<char, SgType*>>& typesByFunctions,
vector<int>& dvmDirErrorsLines)
{
set<SgSymbol*> allVars, allVarsConst;
map<char, SgType*> types;
vector<SgSymbol*> varsWithoutDecl, varsWithoutDeclConst;
set<SgSymbol*> toRename;
InitTypes(types);
FillCommonTypes(types);
auto cp = function->controlParent();
if (isSgProgHedrStmt(cp))
if (typesByFunctions.find(cp) != typesByFunctions.end())
for (auto& parentType : typesByFunctions.at(cp))
types[parentType.first] = parentType.second;
auto hasImplicitNone = false;
auto endOfFunc = function->lastNodeOfStmt();
for (auto st = function; st != endOfFunc; st = st->lexNext())
{
if (st->variant() == IMPL_DECL)
{
SgImplicitStmt* implicitStatement = isSgImplicitStmt(st);
if (implicitStatement != NULL)
{
const int numberOfTypes = implicitStatement->numberOfImplicitTypes();
if (numberOfTypes > 0)
{
for (int j = 0; j < numberOfTypes; ++j)
{
SgType* type = implicitStatement->implicitType(j);
SgExpression* lettersExpression = implicitStatement->implicitRangeList(j);
AddLettersToMap(lettersExpression, type, types);
}
}
else
hasImplicitNone = true;
}
}
else if (st->variant() == CONTAINS_STMT || isSgExecutableStatement(st) != NULL)
break;
}
set<int> skip = { EXTERN_STAT, PRIVATE_STMT, PUBLIC_STMT };
set<SgSymbol*> allDataSymbols;
for (auto s = function->symbol()->next(); s; s = s->next())
if ((s->attributes() & DATA_BIT) && s->scope() == function)
allDataSymbols.insert(s);
set<string> functionSymbs = { function->symbol()->identifier() };
if (isSgFuncHedrStmt(function))
{
SgFuncHedrStmt* hedr = isSgFuncHedrStmt(function);
if (hedr->resultName())
functionSymbs.insert(hedr->resultName()->identifier());
}
auto prog = isSgProgHedrStmt(function);
if (prog)
{
for (int z = 0; z < prog->numberOfInternalSubroutinesDefined(); ++z)
functionSymbs.insert(prog->internalSubroutine(z)->symbol()->identifier());
for (int z = 0; z < prog->numberOfInternalFunctionsDefined(); ++z)
functionSymbs.insert(prog->internalFunction(z)->symbol()->identifier());
}
for (auto st = function->lexNext(); st != endOfFunc && st->variant() != CONTAINS_STMT; st = st->lexNext())
{
if (skip.count(st->variant()))
continue;
if (isDVM_stat(st))
dvmDirErrorsLines.push_back(st->lineNumber());
if (isDVM_stat(st) || isSPF_stat(st))
continue;
if (st->variant() == INTERFACE_STMT)
{
st = st->lastNodeOfStmt();
continue;
}
if (st->variant() == DATA_DECL)
{
const string str = st->expr(0)->thellnd->entry.string_val;
for (auto& data : allDataSymbols)
{
if (str.find(data->identifier()) != string::npos)
allVars.insert(data);
}
}
for (int i = 0; i < 3; ++i)
FindAllVars(st->expr(i), allVars, allVarsConst, function);
if (st->variant() == FOR_NODE)
if (!isByUse(isSgForStmt(st)->doName(), function))
allVars.insert(isSgForStmt(st)->doName());
}
//add parameters
if (prog)
{
for (int z = 0; z < prog->numberOfParameters(); ++z)
{
auto s = prog->parameter(z);
if ((s->attributes() & EXTERNAL_BIT) == 0)
allVars.insert(s);
}
}
varsWithoutDecl = getVars(functionSymbs, toRename, allVars, types, function);
varsWithoutDeclConst = getVars(functionSymbs, toRename, allVarsConst, types, NULL);
if (!hasImplicitNone)
{
vector<SgStatement*> macro;
for (auto st = function->lexNext();
st != endOfFunc && st->variant() != CONTAINS_STMT && isSgExecutableStatement(st) == NULL;
)
{
if (st->variant() == IMPL_DECL)
{
auto tmpStatement = st;
st = st->lexNext();
tmpStatement->deleteStmt();
}
else if (st->variant() == STMTFN_STAT)
{
auto stat = st;
st = st->lexNext();
macro.push_back(stat->extractStmt());
}
else
st = st->lexNext();
}
auto implNone = new SgStatement(IMPL_DECL);
implNone->setlineNumber(function->lineNumber());
implNone->setFileName(function->fileName());
SgStatement* insertPlace = function;
while (insertPlace->lexNext()->variant() == USE_STMT)
insertPlace = insertPlace->lexNext();
insertPlace->insertStmtAfter(*implNone, *function);
insertPlace = insertPlace->lexNext();
if (function->variant() == FUNC_HEDR)
{
SgFuncHedrStmt* hedr = isSgFuncHedrStmt(function);
auto type_op = function->expr(1);
if (type_op == NULL)
{
if (hedr->resultName())
varsWithoutDecl.push_back(hedr->resultName());
else
varsWithoutDecl.push_back(function->symbol());
}
}
makeDeclaration(varsWithoutDecl, function);
auto declList = makeDeclaration(varsWithoutDeclConst, NULL);
for (auto& decl : declList)
insertPlace->insertStmtAfter(*decl, *function);
if (macro.size())
{
while (!isSgExecutableStatement(insertPlace) && insertPlace != NULL)
insertPlace = insertPlace->lexNext();
if (insertPlace == NULL)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (auto& elem : macro)
insertPlace->insertStmtBefore(*elem, *function);
}
}
for (auto& s : toRename)
s->changeName(TestAndCorrectName((string(s->identifier()) + "_").c_str()));
return types;
}
void implicitCheck(SgFile* file, vector<int>& dvmDirErrorsLines)
{
map<SgStatement*, map<char, SgType*>> typesByFunctions;
vector<SgStatement*> modulesAndFunctions;
getModulesAndFunctions(file, modulesAndFunctions);
const string currFile = file->filename();
for (int func = 0; func < modulesAndFunctions.size(); ++func)
{
SgStatement* function = modulesAndFunctions[func];
if (function->fileName() != currFile)
continue;
typesByFunctions[function] = FunctionImplicitCheck(function, typesByFunctions, dvmDirErrorsLines);
}
typesByFunctions.clear();
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include <vector>
void implicitCheck(SgFile* file, std::vector<int>& dvmDirErrorsLines);

View File

@@ -0,0 +1,333 @@
#include <cstdio>
#include <cstring>
#include <cstring>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <set>
#include <vector>
#include "swap_array_dims.h"
#include "../Distribution/Array.h"
#include "dvm.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../Utils/SgUtils.h"
using namespace std;
static bool recSwapExpression(SgExpression *ex, const map<string, vector<int>> &arraysToSwap)
{
bool res = false;
if (ex)
{
if (ex->variant() == ARRAY_REF)
{
string arrayName = ex->symbol()->identifier();
auto it = arraysToSwap.find(arrayName);
if (it != arraysToSwap.end() && ex->lhs())
{
vector<SgExpression*> last;
for (SgExpression *list = ex->lhs(); list; list = list->rhs())
last.push_back(list->lhs());
int i = 0;
if (last.size() == it->second.size())
{
for (SgExpression *list = ex->lhs(); list; list = list->rhs(), ++i)
list->setLhs(last[it->second[i]]);
res = true;
}
}
}
bool tmpR = recSwapExpression(ex->lhs(), arraysToSwap);
res = res || tmpR;
tmpR = recSwapExpression(ex->rhs(), arraysToSwap);
res = res || tmpR;
}
return res;
}
//TODO: use Array
void SwapArrayDims(SgFile *file, const map<string, vector<int>> &arraysToSwap)
{
bool wasDecl = false;
bool wasExec = false;
for (int i = 0; i < file->numberOfFunctions(); ++i)
{
for (SgStatement* st = file->firstStatement(); st; st = st->lexNext())
{
bool isExec = isSgExecutableStatement(st);
for (int i = 0; i < 3; ++i)
{
bool res = recSwapExpression(st->expr(i), arraysToSwap);
if (isExec)
wasExec = wasExec || res;
else
wasDecl = wasDecl || res;
}
}
}
if (wasExec)
__spf_print(1, "wasExec swap in file %s\n", file->filename());
if (wasDecl)
__spf_print(1, "wasDECL swap in file %s\n", file->filename());
}
static void addToNonDecl(SgExpression *ex, set<SgSymbol*> &notDeclarated)
{
if (ex)
{
if (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF)
{
auto toCheck = OriginalSymbol(ex->symbol());
if (toCheck->variant() != FUNCTION_NAME)
{
if (declaratedInStmt(toCheck, NULL, false) == NULL)
notDeclarated.insert(toCheck);
}
}
addToNonDecl(ex->lhs(), notDeclarated);
addToNonDecl(ex->rhs(), notDeclarated);
}
}
static void makeInit(SgExpression *exList, const set<string> &argNames, const set<string> &commonNames)
{
for (auto ex = exList; ex; ex = ex->rhs())
{
auto s = ex->lhs()->symbol();
if (s)
{
bool isInData = (s->attributes() & DATA_BIT) != 0;
if (!isInData && s->type() && s->type()->variant() != T_STRING &&
ex->lhs()->variant() != ASSGN_OP &&
ex->lhs()->symbol()->variant() != FUNCTION_NAME &&
ex->lhs()->symbol()->variant() != CONST_NAME &&
argNames.find(ex->lhs()->symbol()->identifier()) == argNames.end() &&
commonNames.find(ex->lhs()->symbol()->identifier()) == commonNames.end())
{
//printf("%d\n", ex->lhs()->symbol()->variant());
SgExpression* initOp = NULL;
if (s->type()->variant() == T_BOOL)
initOp = new SgExpression(ASSGN_OP, ex->lhs(), new SgValueExp(false));
else if (s->type()->variant() != T_STRUCT)
initOp = new SgExpression(ASSGN_OP, ex->lhs(), new SgValueExp(0));
if (initOp)
ex->setLhs(initOp);
}
}
}
}
void setAllDeclsWithInitZero(SgFile* file)
{
for (int i = 0; i < file->numberOfFunctions(); ++i)
{
set<string> argNames;
auto func = isSgProgHedrStmt(file->functions(i));
checkNull(func, convertFileName(__FILE__).c_str(), __LINE__);
if (func->variant() != PROG_HEDR)
{
for (int z = 0; z < func->numberOfParameters(); ++z)
argNames.insert(func->parameter(z)->identifier());
}
map<string, vector<SgExpression*>> commonBlocks;
getCommonBlocksRef(commonBlocks, func, func->lastNodeOfStmt());
set<string> commonNames;
for (auto& elem : commonBlocks)
for (auto& elemName : elem.second)
for (SgExpression* currCommon = elemName->lhs(); currCommon; currCommon = currCommon->rhs())
commonNames.insert(currCommon->lhs()->symbol()->identifier());
set<string> dataNames;
bool hasAllSave = false;
for (SgStatement* st = func; st; st = st->lexNext())
{
if(st->variant() == CONTAINS_STMT)
break;
if (isSgExecutableStatement(st))
break;
if (st->variant() == SAVE_DECL)
{
if (!st->expr(0) && !st->expr(1) && !st->expr(2))
hasAllSave = true;
else
{
for (auto ex = st->expr(0); ex; ex = ex->rhs())
dataNames.insert(ex->lhs()->symbol()->identifier());
}
}
}
if (hasAllSave)
continue;
for (SgStatement* st = func; st; st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (isSgExecutableStatement(st))
break;
auto decl = isSgDeclarationStatement(st);
if (decl && st->variant() != DATA_DECL)
makeInit(decl->expr(0), argNames, commonNames);
}
set<SgSymbol*> notDeclarated;
for (SgStatement* st = func; st != func->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (!isSgExecutableStatement(st))
continue;
for (int z = 0; z < 3; ++z)
addToNonDecl(st->expr(z), notDeclarated);
}
if (notDeclarated.size())
{
map<int, set<SgSymbol*>> groupedByType;
for (auto& elem : notDeclarated)
groupedByType[elem->type()->id()].insert(elem);
for (auto& gr : groupedByType)
{
vector<SgSymbol*> group(gr.second.begin(), gr.second.end());
auto declStat = makeDeclaration(func, group);
makeInit(declStat->expr(0), argNames, commonNames);
}
}
//insert SAVE without variables
/*SgStatement* firstExec = NULL;
for (SgStatement* st = func; st != func->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (isSgExecutableStatement(st))
{
firstExec = st;
break;
}
}
firstExec->insertStmtBefore(*new SgStatement(SAVE_DECL), *func);*/
}
vector<SgStatement*> modules;
findModulesInFile(file, modules);
for (auto& mod : modules)
{
for (auto st = mod->lexNext(); st != mod->lastNodeOfStmt(); st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
auto decl = isSgDeclarationStatement(st);
set<string> empty;
if (decl && st->variant() != DATA_DECL)
makeInit(decl->expr(0), empty, empty);
}
}
}
static void addTextInit(SgStatement* decl, map<pair<string, int>, string> &symbols)
{
for (auto ex = decl->expr(0); ex; ex = ex->rhs())
{
if (ex->lhs()->variant() == ASSGN_OP)
symbols[make_pair(ex->lhs()->lhs()->symbol()->identifier(), decl->lineNumber())] = string(" ") + ex->lhs()->unparse();
else if (ex->lhs()->symbol() && ((ex->lhs()->symbol()->attributes() & DATA_BIT) != 0))
symbols[make_pair(ex->lhs()->symbol()->identifier(), decl->lineNumber())] = string(" '") + ex->lhs()->symbol()->identifier() + string("' inited from DATA");
}
}
void dumpAllDeclsWithInit(SgFile* file, bool create)
{
string dumpF = string("dump_decls.txt");
FILE* fDump = NULL;
if (create)
fDump = fopen(dumpF.c_str(), "w");
else
fDump = fopen(dumpF.c_str(), "a+");
checkNull(fDump, convertFileName(__FILE__).c_str(), __LINE__);
map<string, string> dumpTextByFunc;
for (int i = 0; i < file->numberOfFunctions(); ++i)
{
string dumpText = "";
auto func = isSgProgHedrStmt(file->functions(i));
checkNull(func, convertFileName(__FILE__).c_str(), __LINE__);
dumpText += string("FOR FUNC ") + func->symbol()->identifier() + "\n";
map<pair<string, int>, string> symbols;
for (SgStatement* st = func->lexNext(); st; st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (isSgExecutableStatement(st))
break;
auto decl = isSgDeclarationStatement(st);
if (decl && st->variant() != DATA_DECL)
addTextInit(decl, symbols);
}
for (auto& elem : symbols)
dumpText += elem.second + "\n";
dumpTextByFunc[func->symbol()->identifier()] = dumpText;
}
vector<SgStatement*> mods;
findModulesInFile(file, mods);
for (auto& mod : mods)
{
string dumpText = string("FOR MODULE ") + mod->symbol()->identifier() + "\n";
map<pair<string, int>, string> symbols;
for (SgStatement* st = mod->lexNext(); st; st = st->lexNext())
{
if (st->variant() == CONTAINS_STMT)
break;
if (isSgExecutableStatement(st))
break;
auto decl = isSgDeclarationStatement(st);
if (decl && st->variant() != DATA_DECL)
{
for (auto ex = decl->expr(0); ex; ex = ex->rhs())
addTextInit(decl, symbols);
}
}
for (auto& elem : symbols)
dumpText += elem.second + "\n";
dumpTextByFunc[string("_module_") + mod->symbol()->identifier()] = dumpText;
}
for (auto& elem : dumpTextByFunc)
fprintf(fDump, "%s\n", elem.second.c_str());
fclose(fDump);
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "dvm.h"
#include <vector>
#include <map>
#include <string>
void SwapArrayDims(SgFile *file, const std::map<std::string, std::vector<int>> &arraysToSwap);
void setAllDeclsWithInitZero(SgFile* file);
void dumpAllDeclsWithInit(SgFile* file, bool create);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
#pragma once
#include "../GraphCall/graph_calls.h"
#include <map>
#include <string>
#include <vector>
bool duplicateFunctions(const std::map<std::string, std::vector<FuncInfo*>> &allFuncs, const std::map<DIST::Array*, std::set<DIST::Array*>>& arrayLinksByFuncCall, std::map<std::string, std::vector<Messages>>& messages);
void removeCopies(const std::map<std::string, std::vector<FuncInfo*>>& funcs);
void restoreCopies(SgFile* file);