moved
This commit is contained in:
536
Sapfor/_src/DirectiveProcessing/directive_omp_parser.cpp
Normal file
536
Sapfor/_src/DirectiveProcessing/directive_omp_parser.cpp
Normal file
@@ -0,0 +1,536 @@
|
||||
#include "../Utils/leak_detector.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
#include "dvm.h"
|
||||
#include "directive_omp_parser.h"
|
||||
#include "directive_parser.h"
|
||||
|
||||
#include "../Utils/SgUtils.h"
|
||||
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using std::set;
|
||||
using std::string;
|
||||
|
||||
|
||||
void removeOmpDir(SgStatement* st)
|
||||
{
|
||||
char* lineS = st->comments();
|
||||
if (!lineS)
|
||||
return;
|
||||
|
||||
vector<string> split;
|
||||
splitString(lineS, '\n', split);
|
||||
|
||||
int idx = 0;
|
||||
for (auto& elem : split)
|
||||
{
|
||||
string line = elem;
|
||||
convertToLower(line);
|
||||
if (line.substr(0, 5) == "!$omp")
|
||||
lineS[idx + 1] = '_';
|
||||
else if (line.substr(0, 3) == "!$ ")
|
||||
lineS[idx + 1] = '_';
|
||||
idx += line.size() + 1; // with '\n'
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addToAttribute(SgStatement* st, int var, vector<SgExpression*> list)
|
||||
{
|
||||
if (list.size())
|
||||
{
|
||||
SgExprListExp* ex = new SgExprListExp();
|
||||
ex->setLhs(new SgExpression(var, makeExprList(list), NULL));
|
||||
SgStatement* toAdd = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, ex, NULL, NULL);
|
||||
toAdd->setlineNumber(st->lineNumber());
|
||||
toAdd->setLocalLineNumber(SPF_OMP_DIR);
|
||||
|
||||
//filter
|
||||
if (var == ACC_PRIVATE_OP)
|
||||
{
|
||||
vector<SgExpression*> list_new;
|
||||
|
||||
auto attributes = getAttributes<SgStatement*, SgStatement*>(st, set<int>{SPF_ANALYSIS_DIR});
|
||||
set<string> privates;
|
||||
for (auto& attr : attributes)
|
||||
fillPrivatesFromComment(new Statement(attr), privates);
|
||||
|
||||
if (privates.size())
|
||||
{
|
||||
for (auto& elem : list)
|
||||
if (privates.find(elem->unparse()) == privates.end())
|
||||
list_new.push_back(elem);
|
||||
list = list_new;
|
||||
|
||||
if (!list.size())
|
||||
{
|
||||
__spf_print(1, "-- skip privates on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (var == REDUCTION_OP)
|
||||
{
|
||||
auto attributes = getAttributes<SgStatement*, SgStatement*>(st, set<int>{SPF_ANALYSIS_DIR});
|
||||
map<string, set<string>> reduction;
|
||||
for (auto& attr : attributes)
|
||||
fillReductionsFromComment(new Statement(attr), reduction);
|
||||
|
||||
map<string, set<string>> reductionToAdd;
|
||||
fillReductionsFromComment(new Statement(toAdd), reductionToAdd);
|
||||
|
||||
vector<SgExpression*> list_new;
|
||||
if (reduction.size())
|
||||
{
|
||||
if (reduction == reductionToAdd)
|
||||
{
|
||||
__spf_print(1, "-- skip reduction on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
return;
|
||||
}
|
||||
|
||||
map<string, set<string>> reductionToAddNew;
|
||||
for (auto& redPair : reductionToAdd)
|
||||
{
|
||||
auto it = reduction.find(redPair.first);
|
||||
if (it == reduction.end())
|
||||
reductionToAddNew[redPair.first] = redPair.second;
|
||||
else
|
||||
{
|
||||
set<string> newVar;
|
||||
for (auto& var : redPair.second)
|
||||
{
|
||||
auto itVar = it->second.find(var);
|
||||
if (itVar == it->second.end())
|
||||
reductionToAddNew[redPair.first].insert(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!reductionToAddNew.size())
|
||||
{
|
||||
__spf_print(1, "-- skip reduction on line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
return;
|
||||
}
|
||||
|
||||
if (reductionToAddNew != reductionToAdd)
|
||||
{
|
||||
list.clear();
|
||||
for (auto& redPair : reductionToAddNew)
|
||||
for (auto& var : redPair.second)
|
||||
list.push_back(new SgExpression(ARRAY_OP,
|
||||
new SgKeywordValExp(redPair.first.c_str()),
|
||||
new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ex = new SgExprListExp();
|
||||
ex->setLhs(new SgExpression(var, makeExprList(list), NULL));
|
||||
toAdd = new SgStatement(SPF_ANALYSIS_DIR, NULL, NULL, ex, NULL, NULL);
|
||||
|
||||
st->addAttribute(SPF_ANALYSIS_DIR, toAdd, sizeof(SgStatement));
|
||||
|
||||
if (var == ACC_PRIVATE_OP)
|
||||
__spf_print(1, "-- set private attribute to line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
else if (var == REDUCTION_OP)
|
||||
__spf_print(1, "-- set reduction attribute to line %d from OMP dir\n%s", st->lineNumber(), toAdd->unparse());
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_write_in_do(SgStatement* st, const string& var)
|
||||
{
|
||||
checkNull(st, convertFileName(__FILE__).c_str(), __LINE__);
|
||||
|
||||
if (st->variant() != FOR_NODE)
|
||||
return false;
|
||||
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
for (SgStatement* op = st->lexNext(); st != lastNode; st = st->lexNext())
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
SgExpression* ex = st->expr(0);
|
||||
if (ex->variant() == ARRAY_REF || ex->variant() == VAR_REF)
|
||||
if (var == ex->symbol()->identifier())
|
||||
return true;
|
||||
}
|
||||
else if (st->variant() == FOR_NODE)
|
||||
{
|
||||
if (var == isSgForStmt(st)->doName()->identifier())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<OmpDir> parseOmpInStatement(SgStatement* st, const set<string>& globalPriv, bool forDo)
|
||||
{
|
||||
vector<OmpDir> resultAll;
|
||||
|
||||
const char* lineS = st->comments();
|
||||
if (!lineS)
|
||||
return resultAll;
|
||||
|
||||
string comment(lineS);
|
||||
convertToLower(comment);
|
||||
|
||||
vector<string> split;
|
||||
splitString(comment, '\n', split);
|
||||
|
||||
for (int z = split.size() - 1; z >= 0; z--)
|
||||
{
|
||||
string line = split[z];
|
||||
|
||||
if (line.substr(0, 6) == "!$omp&")
|
||||
{
|
||||
if (z - 1 < 0)
|
||||
break;
|
||||
split[z - 1] += line.substr(6);
|
||||
split[z] = "";
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& line : split)
|
||||
{
|
||||
if (line.substr(0, 5) == "!$omp")
|
||||
{
|
||||
OmpDir result;
|
||||
|
||||
string line1 = "";
|
||||
int space = 0;
|
||||
int brake = 0;
|
||||
for (int z = 0; z < line.size(); ++z)
|
||||
{
|
||||
if (brake < 0)
|
||||
return vector<OmpDir>(); // error
|
||||
|
||||
if (brake == 0)
|
||||
{
|
||||
if (line[z] == ' ')
|
||||
space++;
|
||||
else
|
||||
space = 0;
|
||||
if ((line[z] == ' ' && space <= 1) || line[z] != ' ')
|
||||
line1 += line[z];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line[z] != ' ')
|
||||
line1 += line[z];
|
||||
}
|
||||
|
||||
if (line[z] == '(')
|
||||
{
|
||||
while (line1.size() > 2 && line1[line1.size() - 2] == ' ')
|
||||
line1 = line1.erase(line1.size() - 2, 1);
|
||||
brake++;
|
||||
space = 0;
|
||||
}
|
||||
else if (line[z] == ')')
|
||||
brake--;
|
||||
}
|
||||
vector<string> lexems;
|
||||
splitString(line1, ' ', lexems);
|
||||
bool doLexem = false;
|
||||
bool end = false;
|
||||
bool parallel = false;
|
||||
bool privat = false;
|
||||
|
||||
for (auto& lexem : lexems)
|
||||
{
|
||||
if (lexem == "do")
|
||||
{
|
||||
doLexem = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
if (lexem == "end")
|
||||
{
|
||||
end = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
if (lexem == "parallel")
|
||||
{
|
||||
parallel = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
if (lexem == "private")
|
||||
{
|
||||
privat = true;
|
||||
result.keys.insert(lexem);
|
||||
}
|
||||
}
|
||||
|
||||
if (privat == false)
|
||||
{
|
||||
if (forDo && doLexem)
|
||||
{
|
||||
vector<SgExpression*> list;
|
||||
for (auto& var : globalPriv)
|
||||
if (is_write_in_do(st, var))
|
||||
list.push_back(new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st))));
|
||||
|
||||
if (list.size())
|
||||
addToAttribute(st, ACC_PRIVATE_OP, list);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& lexem : lexems)
|
||||
{
|
||||
bool priv = lexem.substr(0, strlen("private(")) == "private(";
|
||||
bool threadpriv = lexem.substr(0, strlen("threadprivate(")) == "threadprivate(";
|
||||
bool red = lexem.substr(0, strlen("reduction(")) == "reduction(";
|
||||
if (priv || threadpriv)
|
||||
{
|
||||
vector<string> sublex;
|
||||
splitString(lexem, '(', sublex);
|
||||
if (sublex.size() == 2 && lexem.back() == ')')
|
||||
{
|
||||
splitString(sublex[1].erase(sublex[1].size() - 1), ',', sublex);
|
||||
|
||||
vector<SgExpression*> list;
|
||||
set<string> uniqList;
|
||||
for (auto& varG : globalPriv)
|
||||
uniqList.insert(varG);
|
||||
|
||||
for (auto& var : sublex)
|
||||
uniqList.insert(var);
|
||||
|
||||
for (auto& var : uniqList)
|
||||
{
|
||||
if (priv)
|
||||
{
|
||||
result.privVars.insert(var);
|
||||
list.push_back(new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st))));
|
||||
}
|
||||
else
|
||||
result.threadPrivVars.insert(var);
|
||||
}
|
||||
|
||||
if (forDo && doLexem && priv)
|
||||
addToAttribute(st, ACC_PRIVATE_OP, list);
|
||||
}
|
||||
}
|
||||
else if (red)
|
||||
{
|
||||
vector<string> sublex;
|
||||
splitString(lexem, '(', sublex);
|
||||
if (sublex.size() == 2 && lexem.back() == ')')
|
||||
{
|
||||
splitString(sublex[1].erase(sublex[1].size() - 1), ':', sublex);
|
||||
|
||||
vector<string> vars;
|
||||
vector<SgExpression*> list;
|
||||
splitString(sublex[1], ',', vars);
|
||||
string op = "";
|
||||
|
||||
if (sublex[0] == "+")
|
||||
op = "sum";
|
||||
else if (sublex[0] == "*")
|
||||
op = "prod";
|
||||
else if (sublex[0] == "max")
|
||||
op = "max";
|
||||
else if (sublex[0] == "min")
|
||||
op = "min";
|
||||
else if (sublex[0] == ".or." || sublex[0] == "or")
|
||||
op = "or";
|
||||
else if (sublex[0] == ".and." || sublex[0] == "and")
|
||||
op = "and";
|
||||
else if (sublex[0] == ".eqv." || sublex[0] == "eqv")
|
||||
op = "eqv";
|
||||
else if (sublex[0] == ".neqv." || sublex[0] == "neqv")
|
||||
op = "neqv";
|
||||
|
||||
if (op != "")
|
||||
{
|
||||
for (auto& var : vars)
|
||||
{
|
||||
result.redVars[sublex[0]].insert(var);
|
||||
list.push_back(new SgExpression(ARRAY_OP, new SgKeywordValExp(op.c_str()), new SgVarRefExp(findSymbolOrCreate(current_file, var, NULL, getFuncStat(st)))));
|
||||
}
|
||||
}
|
||||
|
||||
if (forDo && doLexem && op != "")
|
||||
addToAttribute(st, REDUCTION_OP, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resultAll.push_back(result);
|
||||
}
|
||||
}
|
||||
|
||||
return resultAll;
|
||||
}
|
||||
|
||||
//TODO: need to use IR and RD for checking
|
||||
static void filterPrivates(OmpDir& dir)
|
||||
{
|
||||
if (dir.privVars.size() == 0)
|
||||
return;
|
||||
|
||||
for (auto st = dir.start; st != dir.end; st = st->lexNext())
|
||||
{
|
||||
vector<OmpDir> res;
|
||||
if (st != dir.start)
|
||||
{
|
||||
set<string> dummy;
|
||||
res = parseOmpInStatement(st, dummy);
|
||||
}
|
||||
|
||||
bool hasParallelDo = false;
|
||||
for (auto& dir : res)
|
||||
{
|
||||
if (dir.keys.find("parallel") != dir.keys.end() ||
|
||||
dir.keys.find("do") != dir.keys.end())
|
||||
{
|
||||
hasParallelDo = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (res.size() == 0 || !hasParallelDo)
|
||||
{
|
||||
if (st->variant() == ASSIGN_STAT)
|
||||
{
|
||||
if (st->expr(0))
|
||||
{
|
||||
string ref = st->expr(0)->symbol()->identifier();
|
||||
dir.privVars.erase(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static vector<OmpDir> findAllGlobalParallelRegions(SgStatement* stFunc)
|
||||
{
|
||||
vector<OmpDir> sections;
|
||||
|
||||
SgStatement* lastNode = stFunc->lastNodeOfStmt();
|
||||
for (auto st = stFunc; st != lastNode; st = st->lexNext())
|
||||
{
|
||||
if (st == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
set<string> dummy;
|
||||
auto res = parseOmpInStatement(st, dummy);
|
||||
|
||||
for (auto& dir : res)
|
||||
{
|
||||
auto end = dir.keys.end();
|
||||
if (dir.keys.find("parallel") != end
|
||||
&& dir.keys.find("do") == end
|
||||
&& dir.keys.find("end") == end)
|
||||
{
|
||||
if (sections.size() && sections.back().end == NULL) // has open parallel region
|
||||
{
|
||||
__spf_print(1, "wrong omp directives placed on line %d\n", st->lineNumber());
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
|
||||
sections.push_back(dir);
|
||||
sections.back().start = st;
|
||||
}
|
||||
else if (dir.keys.find("parallel") != end
|
||||
&& dir.keys.find("do") == end
|
||||
&& dir.keys.find("end") != end)
|
||||
{
|
||||
if (!sections.size())
|
||||
{
|
||||
__spf_print(1, "wrong omp directives placed on line %d\n", st->lineNumber());
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
sections.back().end = st;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& dir : sections)
|
||||
filterPrivates(dir);
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
static set<string> getGlobalPrivate(SgStatement* st, const vector<OmpDir>& globalParallelRegions)
|
||||
{
|
||||
set<string> globalPrivates;
|
||||
const int line = st->lineNumber();
|
||||
if (line > 0)
|
||||
{
|
||||
for (auto& reg : globalParallelRegions)
|
||||
{
|
||||
if (reg.start->lineNumber() <= line && line < reg.end->lineNumber())
|
||||
{
|
||||
if (reg.privVars.size())
|
||||
return reg.privVars;
|
||||
else
|
||||
return globalPrivates;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (auto& reg : globalParallelRegions)
|
||||
{
|
||||
for (auto stF = reg.start; stF != reg.end; stF = stF->lexNext())
|
||||
{
|
||||
if (st == stF)
|
||||
{
|
||||
if (reg.privVars.size())
|
||||
return reg.privVars;
|
||||
else
|
||||
return globalPrivates;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return globalPrivates;
|
||||
}
|
||||
|
||||
void parseOmpDirectives(SgFile* file, vector<Messages>& currMessages)
|
||||
{
|
||||
int funcNum = file->numberOfFunctions();
|
||||
|
||||
for (int i = 0; i < funcNum; ++i)
|
||||
{
|
||||
SgStatement* st = file->functions(i);
|
||||
SgStatement* lastNode = st->lastNodeOfStmt();
|
||||
|
||||
vector<OmpDir> globalParallelRegions = findAllGlobalParallelRegions(st);
|
||||
|
||||
while (st != lastNode)
|
||||
{
|
||||
if (st == NULL)
|
||||
{
|
||||
__spf_print(1, "internal error in analysis, parallel directives will not be generated for this file!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (st->variant() == CONTAINS_STMT)
|
||||
break;
|
||||
|
||||
if (st->variant() == FOR_NODE)
|
||||
{
|
||||
SgForStmt* currSt = (SgForStmt*)st;
|
||||
if (currSt->isEnddoLoop() == 0)
|
||||
{
|
||||
__spf_print(1, "wrong omp directives placed\n");
|
||||
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
|
||||
}
|
||||
else
|
||||
parseOmpInStatement(st, getGlobalPrivate(st, globalParallelRegions), true);
|
||||
}
|
||||
st = st->lexNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user