diff --git a/CMakeLists.txt b/CMakeLists.txt index 12e61a7..02022ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,11 +161,11 @@ set(PARALLEL_REG src/ParallelizationRegions/ParRegions.cpp src/ParallelizationRegions/expand_extract_reg.cpp src/ParallelizationRegions/expand_extract_reg.h src/ParallelizationRegions/resolve_par_reg_conflicts.cpp - src/ParallelizationRegions/resolve_par_reg_conflicts.h) - -set(ARRAY_PROP src/ArrayConstantPropagation/propagation.cpp - src/ArrayConstantPropagation/propagation.h -) + src/ParallelizationRegions/resolve_par_reg_conflicts.h + src/ParallelizationRegions/uniq_name_creator.cpp + src/ParallelizationRegions/uniq_name_creator.h + src/ParallelizationRegions/merge_regions.h + src/ParallelizationRegions/merge_regions.cpp) set(TR_DEAD_CODE src/Transformations/DeadCodeRemoving/dead_code.cpp src/Transformations/DeadCodeRemoving/dead_code.h) @@ -210,6 +210,8 @@ set(TR_RENAME_SYMBOLS src/Transformations/RenameSymbols/rename_symbols.cpp src/Transformations/RenameSymbols/rename_symbols.h) SET(TR_MOVE_OPERATORS src/Transformations/MoveOperators/move_operators.cpp src/Transformations/MoveOperators/move_operators.h) +SET(TR_ARR_PROP src/Transformations/ArrayConstantPropagation/propagation.cpp + src/Transformations/ArrayConstantPropagation/propagation.h) set(TRANSFORMS ${TR_DEAD_CODE} @@ -233,7 +235,8 @@ set(TRANSFORMS ${TR_EXPR_TRANSFORM} ${TR_INLINER} ${TR_RENAME_SYMBOLS} - ${TR_MOVE_OPERATORS}) + ${TR_MOVE_OPERATORS} + ${TR_ARR_PROP}) set(CFG src/CFGraph/IR.cpp src/CFGraph/IR.h @@ -427,7 +430,6 @@ set(SOURCE_EXE ${TRANSFORMS} ${PARALLEL_REG} ${PRIV} - ${ARRAY_PROP} ${FDVM} ${OMEGA} ${UTILS} @@ -468,6 +470,7 @@ source_group (Transformations\\ConvertToC FILES ${TR_CONV}) source_group (Transformations\\SetImplicitNone FILES ${TR_IMPLICIT_NONE}) source_group (Transformations\\ReplaceArraysInIO FILES ${TR_REPLACE_ARRAYS_IN_IO}) source_group (Transformations\\MoveOperators FILES ${TR_MOVE_OPERATORS}) +source_group (Transformations\\ArrayConstantPropagation FILES ${TR_ARR_PROP}) source_group (CreateIntervals FILES ${CREATE_INTER_T}) @@ -480,7 +483,6 @@ source_group (GraphLoop FILES ${GR_LOOP}) source_group (LoopAnalyzer FILES ${LOOP_ANALYZER}) source_group (ParallelizationRegions FILES ${PARALLEL_REG}) source_group (PrivateAnalyzer FILES ${PRIV}) -source_group (ArrayConstantPropagation FILES ${ARRAY_PROP}) source_group (FDVM_Compiler FILES ${FDVM}) source_group (SageExtension FILES ${OMEGA}) source_group (Utils FILES ${UTILS}) diff --git a/src/ArrayConstantPropagation/propagation.cpp b/src/ArrayConstantPropagation/propagation.cpp deleted file mode 100644 index bf56a3f..0000000 --- a/src/ArrayConstantPropagation/propagation.cpp +++ /dev/null @@ -1,301 +0,0 @@ -#include "propagation.h" - -#include "../Utils/SgUtils.h" - -#include -#include -#include -#include - -using namespace std; - -static SgStatement* declPlace = NULL; - -static bool CheckConstIndexes(SgExpression* exp) -{ - if (!exp) - { - return true; - } - SgExpression* lhs = exp->lhs(); - SgExpression* rhs = exp->rhs(); - do - { - if (lhs->variant() != INT_VAL) - { - return false; - } - if (rhs) - { - lhs = rhs->lhs(); - rhs = rhs->rhs(); - } - } while (rhs); - return true; -} - -static SgExpression* CreateVar(int& variableNumber, SgType* type) -{ - string varName = "__tmp_prop_var"; - string name = varName + std::to_string(variableNumber) + "__"; - variableNumber++; - - SgSymbol* varSymbol = new SgSymbol(VARIABLE_NAME, name.c_str(), *type, *declPlace->controlParent()); - - const string commonBlockName = "__propagation_common__"; - - SgStatement* funcStart = declPlace->controlParent(); - SgStatement* commonStat = NULL; - SgExpression* commonList = NULL; - - SgStatement* funcEnd = funcStart->lastNodeOfStmt(); - SgStatement* current = funcStart->lexNext(); - - while (current != funcEnd && current) - { - if (current->variant() == COMM_STAT) - { - for (SgExpression* exp = current->expr(0); exp; exp = exp->rhs()) - { - if (exp->variant() == COMM_LIST) - { - string existingName = exp->symbol() ? - string(exp->symbol()->identifier()) : - string("spf_unnamed"); - if (existingName == commonBlockName) - { - commonStat = current; - commonList = exp; - break; - } - } - } - if (commonStat) - break; - } - current = current->lexNext(); - } - - vector varRefs; - if (commonList) - { - SgExpression* varList = commonList->lhs(); - if (varList) - { - auto extractSymbol = [](SgExpression* exp) -> SgSymbol* { - if (!exp) - return NULL; - if (exp->symbol()) - return exp->symbol(); - if (exp->lhs() && exp->lhs()->symbol()) - return exp->lhs()->symbol(); - return NULL; - }; - if (varList->variant() == EXPR_LIST) - { - for (SgExpression* exp = varList; exp; exp = exp->rhs()) - { - SgExpression* varExp = exp->lhs(); - SgSymbol* sym = extractSymbol(varExp); - if (sym) - { - varRefs.push_back(new SgVarRefExp(sym)); - } - } - } - else - { - for (SgExpression* varExp = varList; varExp; varExp = varExp->rhs()) - { - SgSymbol* sym = extractSymbol(varExp); - if (sym) - { - varRefs.push_back(new SgVarRefExp(sym)); - } - } - } - } - } - - if (!commonList) - { - current = funcStart->lexNext(); - while (current != funcEnd && current) - { - if (current->variant() == COMM_STAT) - { - commonStat = current; - break; - } - current = current->lexNext(); - } - - SgSymbol* commonSymbol = new SgSymbol(COMMON_NAME, commonBlockName.c_str()); - commonList = new SgExpression(COMM_LIST, NULL, NULL, commonSymbol); - - if (commonStat) - { - SgExpression* lastCommList = commonStat->expr(0); - if (lastCommList) - { - while (lastCommList->rhs()) - lastCommList = lastCommList->rhs(); - lastCommList->setRhs(commonList); - } - else - { - commonStat->setExpression(0, commonList); - } - } - else - { - commonStat = new SgStatement(COMM_STAT); - commonStat->setFileName(declPlace->fileName()); - commonStat->setFileId(declPlace->getFileId()); - commonStat->setProject(declPlace->getProject()); - commonStat->setlineNumber(getNextNegativeLineNumber()); - commonStat->setExpression(0, commonList); - - declPlace->insertStmtBefore(*commonStat, *declPlace->controlParent()); - } - - } - varRefs.push_back(new SgVarRefExp(varSymbol)); - - if (varRefs.size() > 0) - { - std::reverse(varRefs.begin(), varRefs.end()); - SgExpression* varList = makeExprList(varRefs, false); - - commonList->setLhs(varList); - } - - return new SgExpression(VAR_REF, NULL, NULL, varSymbol, type->copyPtr()); -} - -static void TransformRightPart(SgStatement* st, SgExpression* exp, unordered_map& arrayToVariable, int& variableNumber) -{ - if (!exp) - { - return; - } - - vector subnodes = { exp->lhs(), exp->rhs() }; - - string expUnparsed; - SgExpression* toAdd = NULL; - if (exp->variant() == ARRAY_REF && CheckConstIndexes(exp->lhs())) - { - cout << st->unparse() << endl; - if (arrayToVariable.find(expUnparsed) == arrayToVariable.end() && exp->symbol()->type()->baseType()) - { - arrayToVariable[expUnparsed] = CreateVar(variableNumber, exp->symbol()->type()->baseType()); - } - st->setExpression(1, arrayToVariable[expUnparsed]->copyPtr()); - return; - } - for (int i = 0; i < 2; i++) - { - if (subnodes[i] && subnodes[i]->variant() == ARRAY_REF && subnodes[i]->symbol()->type()->baseType() && CheckConstIndexes(subnodes[i]->lhs())) - { - expUnparsed = subnodes[i]->unparse(); - if (arrayToVariable.find(expUnparsed) == arrayToVariable.end()) - { - arrayToVariable[expUnparsed] = CreateVar(variableNumber, subnodes[i]->symbol()->type()->baseType());; - } - toAdd = arrayToVariable[expUnparsed]->copyPtr(); - if (toAdd) - { - if (i == 0) - { - exp->setLhs(toAdd); - } - else - { - exp->setRhs(toAdd); - } - } - } - else - { - TransformRightPart(st, subnodes[i], arrayToVariable, variableNumber); - } - } -} - -static void TransformLeftPart(SgStatement* st, SgExpression* exp, unordered_map& arrayToVariable, int& variableNumber) -{ - if (exp->symbol()->type()->variant() == T_STRING) - return; - string expUnparsed = exp->unparse(); - if (arrayToVariable.find(expUnparsed) == arrayToVariable.end() && exp->symbol()->type()->baseType()) - { - arrayToVariable[expUnparsed] = CreateVar(variableNumber, exp->symbol()->type()->baseType()); - } - SgStatement* newStatement = new SgStatement(ASSIGN_STAT, NULL, NULL, arrayToVariable[expUnparsed]->copyPtr(), st->expr(1)->copyPtr(), NULL); - - newStatement->setFileId(st->getFileId()); - newStatement->setProject(st->getProject()); - - newStatement->setlineNumber(getNextNegativeLineNumber()); - newStatement->setLocalLineNumber(st->lineNumber()); - st->insertStmtBefore(*newStatement, *st->controlParent()); -} - -void ArrayConstantPropagation(SgProject& project) -{ - unordered_map arrayToVariable; - int variableNumber = 0; - for (int i = 0; i < project.numberOfFiles(); i++) - { - SgFile* file = &(project.file(i)); - - if (!file) - continue; - - const int funcNum = file->numberOfFunctions(); - for (int i = 0; i < funcNum; ++i) - { - SgStatement* st = file->functions(i); - declPlace = st->lexNext(); - SgStatement* lastNode = st->lastNodeOfStmt(); - - for (; st != lastNode; st = st->lexNext()) - { - if (st->variant() == ASSIGN_STAT) - { - if (st->expr(1)) - { - TransformRightPart(st, st->expr(1), arrayToVariable, variableNumber); - } - if (st->expr(0) && st->expr(0)->variant() == ARRAY_REF && CheckConstIndexes(st->expr(0)->lhs())) - { - TransformLeftPart(st, st->expr(0), arrayToVariable, variableNumber); - } - } - else if (st->variant() == FOR_NODE) - { - SgExpression* lowerBound = st->expr(0)->lhs(); - SgExpression* upperBound = st->expr(0)->rhs(); - string lowerBoundUnparsed = lowerBound->unparse(), upperBoundUnparsed = upperBound->unparse(); - if (upperBound->variant() == ARRAY_REF && upperBound->symbol()->type()->baseType() && CheckConstIndexes(upperBound->lhs())) - { - if (arrayToVariable.find(upperBoundUnparsed) == arrayToVariable.end()) - { - arrayToVariable[upperBoundUnparsed] = CreateVar(variableNumber, upperBound->symbol()->type()->baseType()); - } - st->expr(0)->setRhs(arrayToVariable[upperBoundUnparsed]->copyPtr()); - } - if (lowerBound->variant() == ARRAY_REF && lowerBound->symbol()->type()->baseType() && CheckConstIndexes(lowerBound->lhs())) - { - if (arrayToVariable.find(lowerBoundUnparsed) == arrayToVariable.end()) - { - arrayToVariable[lowerBoundUnparsed] = CreateVar(variableNumber, lowerBound->symbol()->type()->baseType()); - } - st->expr(0)->setLhs(arrayToVariable[lowerBoundUnparsed]->copyPtr()); - } - } - } - } - } -} \ No newline at end of file diff --git a/src/ArrayConstantPropagation/propagation.h b/src/ArrayConstantPropagation/propagation.h deleted file mode 100644 index e2e76cd..0000000 --- a/src/ArrayConstantPropagation/propagation.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "../Utils/SgUtils.h" - -void ArrayConstantPropagation(SgProject& project); \ No newline at end of file diff --git a/src/CFGraph/RD_subst.h b/src/CFGraph/RD_subst.h index e51c51b..d6bda94 100644 --- a/src/CFGraph/RD_subst.h +++ b/src/CFGraph/RD_subst.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "SgUtils.h" #include "CommonBlock.h" diff --git a/src/DirectiveProcessing/directive_parser.cpp b/src/DirectiveProcessing/directive_parser.cpp index e653f26..5af0f02 100644 --- a/src/DirectiveProcessing/directive_parser.cpp +++ b/src/DirectiveProcessing/directive_parser.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -584,6 +583,37 @@ void fillCheckpointFromComment(Statement *stIn, map &clauses, template void fillCheckpointFromComment(Statement *stIn, map &clauses, set &vars, set &expt); template void fillCheckpointFromComment(Statement *stIn, map &clauses, set &vars, set &expt); +template +void fillMergeArraysFromComment(Statement* stIn, pair& toReplace) +{ + if (stIn) + { + SgStatement* st = stIn->GetOriginal(); + if (st->variant() == SPF_TRANSFORM_DIR) + { + SgExpression* exprList = st->expr(0); + while (exprList) + { + const int var = exprList->lhs()->variant(); + if (var == SPF_MERGE_ARRAYS_OP) + { + if (!exprList->lhs()->lhs() || !exprList->lhs()->rhs()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + fillType *dummy = NULL; + toReplace = std::make_pair(getData(exprList->lhs()->lhs(), dummy), + getData(exprList->lhs()->rhs(), dummy)); + break; + } + exprList = exprList->rhs(); + } + } + } +} + +template void fillMergeArraysFromComment(Statement* st, pair& toReplace); +template void fillMergeArraysFromComment(Statement* st, pair& toReplace); + void fillInfoFromDirectives(const LoopGraph *loopInfo, ParallelDirective *directive) { SgForStmt *currentLoop = (SgForStmt*)loopInfo->loop; diff --git a/src/DirectiveProcessing/directive_parser.h b/src/DirectiveProcessing/directive_parser.h index f632940..3e5d954 100644 --- a/src/DirectiveProcessing/directive_parser.h +++ b/src/DirectiveProcessing/directive_parser.h @@ -52,4 +52,7 @@ void fillShrinkFromComment(Statement *stIn, std::vector void fillCheckpointFromComment(Statement *stIn, std::map &clauses, std::set &vars, std::set &expt); +template +void fillMergeArraysFromComment(Statement* stIn, std::pair& toReplace); + int getCoverPropertyFromComment(Statement* stIn); diff --git a/src/DirectiveProcessing/spf_directive_preproc.cpp b/src/DirectiveProcessing/spf_directive_preproc.cpp index 6039de6..191fd8f 100644 --- a/src/DirectiveProcessing/spf_directive_preproc.cpp +++ b/src/DirectiveProcessing/spf_directive_preproc.cpp @@ -186,12 +186,13 @@ static bool checkCover(SgStatement* st, return retVal; } -static bool checkProcessPrivate(SgStatement* st, - SgStatement* attributeStatement, - const set& privates, - vector& messagesForFile) +static bool checkDeclaration(SgStatement* st, + SgStatement* attributeStatement, + const set& variables, + vector& messagesForFile) { // PROCESS_PRIVATE(VAR) + // MERGE_ARRAYS(ARR1, ARR2) const int var = st->variant(); bool retVal = true; @@ -203,12 +204,12 @@ static bool checkProcessPrivate(SgStatement* st, set varDef, varUse; fillVarsSets(iterator, end, varDef, varUse); - for (auto& privElemS : privates) + for (auto& var : variables) { - const string privElem = privElemS->GetOriginal()->identifier(); + const string varElem = var->GetOriginal()->identifier(); bool defCond = true; - if (varDef.find(privElem) == varDef.end()) + if (varDef.find(varElem) == varDef.end()) defCond = false; if (!defCond) @@ -1784,7 +1785,7 @@ static inline bool processStat(SgStatement *st, const string &currFile, fillPrivatesFromComment(new Statement(attributeStatement), privates, SPF_PROCESS_PRIVATE_OP); if (privates.size()) { - bool result = checkProcessPrivate(st, attributeStatement, privates, messagesForFile); + bool result = checkDeclaration(st, attributeStatement, privates, messagesForFile); retVal = retVal && result; } @@ -1933,6 +1934,26 @@ static inline bool processStat(SgStatement *st, const string &currFile, retVal = false; } } + + //MERGE_ARRAYS + if (isSPF_OP(attributeStatement, SPF_MERGE_ARRAYS_OP)) + { + attributeStatement->setLocalLineNumber(-1); + if (!isSgDeclarationStatement(st)) + { + BAD_POSITION_FULL(ERROR, "", "", "before", RR1_1, "declataion statement", RR1_9, attributeStatement->lineNumber()); + retVal = false; + } + else + { + pair toReplacePair; + fillMergeArraysFromComment(new Statement(attributeStatement), toReplacePair); + + set toCheckDecl = { toReplacePair.first }; + bool result = checkDeclaration(st, attributeStatement, toCheckDecl, messagesForFile); + retVal = retVal && result; + } + } } else if (type == SPF_CHECKPOINT_DIR) { diff --git a/src/DvmhRegions/DvmhRegionInserter.cpp b/src/DvmhRegions/DvmhRegionInserter.cpp index 002f40b..5777280 100644 --- a/src/DvmhRegions/DvmhRegionInserter.cpp +++ b/src/DvmhRegions/DvmhRegionInserter.cpp @@ -1289,6 +1289,9 @@ static set SgStatement* declStat = NULL; + if (realArray->GetLocation().first == DIST::l_PARAMETER) + continue; + if (realArray->GetLocation().first == DIST::l_COMMON) { commonArrays.insert(realArray); diff --git a/src/GraphCall/graph_calls.cpp b/src/GraphCall/graph_calls.cpp index 1e44544..1100366 100644 --- a/src/GraphCall/graph_calls.cpp +++ b/src/GraphCall/graph_calls.cpp @@ -723,7 +723,7 @@ static void fillIn(FuncInfo *currF, SgExpression *ex, const map &pa { if (ex) { - if (!isInFuncPar && (ex->variant() == VAR_REF || isArrayRef(ex))) + if (!isInFuncPar && (ex->variant() == VAR_REF || ex->variant() == ARRAY_REF)) { const char *name = ex->symbol()->identifier(); if (name && name != string("")) @@ -800,29 +800,58 @@ static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last, co static map> supportedKeyWordArg = { {"system_clock", { OUT_BIT, OUT_BIT, OUT_BIT } } }; - map parNames; + map parNamesMain; + map parNamesContains; for (int i = 0; i < currF->funcParams.identificators.size(); ++i) - parNames[currF->funcParams.identificators[i]] = i; + parNamesMain[currF->funcParams.identificators[i]] = i; + map& parNames = parNamesMain; + + bool isContainsFunctions = false; for (auto st = start; st != last; st = st->lexNext()) { - if (st->variant() == CONTAINS_STMT) - break; + if (st->variant() == CONTAINS_STMT) { + isContainsFunctions = true; + continue; + } + + if (isContainsFunctions) { + if (st->variant() == PROC_HEDR || st->variant() == FUNC_HEDR) { + parNamesContains = parNamesMain; + + SgProgHedrStmt* hedr = (SgProgHedrStmt*)st; + + int numOfParams = hedr->numberOfParameters(); + if (numOfParams > 0) + { + for (int i = 0; i < numOfParams; ++i) + { + auto it = parNamesContains.find(hedr->parameter(i)->identifier()); + if (it != parNamesContains.end()) + parNamesContains.erase(it); + } + } + parNames = parNamesContains; + } + } if (st->variant() == ENTRY_STAT) continue; if (isSgExecutableStatement(st) == NULL) { - checkInTypeDescription(st->expr(0), currF, parNames); + if (!isContainsFunctions) + checkInTypeDescription(st->expr(0), currF, parNames); continue; } if (st->lineNumber() <= 0) continue; - if (activeOps.size() && activeOps.find(st) == activeOps.end()) - continue; + //XXX: use parameters removing in block ... isContainsFunctions ... + //TODO need to use IR for parameters checking + /*if (activeOps.size() && activeOps.find(st) == activeOps.end()) + continue; */ if (st->variant() == ASSIGN_STAT) { @@ -851,7 +880,7 @@ static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last, co for (auto ex = read->itemList(); ex; ex = ex->rhs()) { SgExpression* item = ex->lhs(); - if (item->variant() == VAR_REF || isArrayRef(item)) + if (item && (item->variant() == VAR_REF || item->variant() == ARRAY_REF)) { string symb = ""; if (item->symbol()) @@ -872,7 +901,7 @@ static void fillInOut(FuncInfo *currF, SgStatement *start, SgStatement *last, co if (item->rhs()) queue.push(item->rhs()); - if (item->variant() == VAR_REF || isArrayRef(item)) + if (item->variant() == VAR_REF || item->variant() == ARRAY_REF) { string symb = ""; if (item->symbol()) diff --git a/src/GraphLoop/graph_loops_base.cpp b/src/GraphLoop/graph_loops_base.cpp index 7a871bb..a6c06d4 100644 --- a/src/GraphLoop/graph_loops_base.cpp +++ b/src/GraphLoop/graph_loops_base.cpp @@ -6,14 +6,12 @@ #include #include -#include #include #include #include using std::vector; using std::map; -using std::unordered_map; using std::tuple; using std::set; using std::string; diff --git a/src/ParallelizationRegions/ParRegions.cpp b/src/ParallelizationRegions/ParRegions.cpp index a05d827..b27531b 100644 --- a/src/ParallelizationRegions/ParRegions.cpp +++ b/src/ParallelizationRegions/ParRegions.cpp @@ -24,6 +24,7 @@ using std::make_pair; using std::map; using std::set; using std::wstring; +using std::tuple; extern void createMapLoopGraph(map &sortedLoopGraph, const vector *loopGraph); @@ -954,4 +955,65 @@ void calculateLinesOfCode(vector &allRegions) __spf_print(1, " Count of lines in region '%s' = %d\n", elem->GetName().c_str(), lineCounter); } +} + +void propagateRegionInfo(map, pair>& declaredArrays, + const map>& arrayLinksByFuncCalls, + const vector ¶llelRegions) +{ + bool modified = true; + while (modified) + { + modified = false; + + for (auto &array_pair: declaredArrays) + { + auto array = array_pair.second.first; + if (array->GetLocation().first == DIST::l_PARAMETER) + { + set realArrayRef; + getAllArrayRefs(array, array, realArrayRef, arrayLinksByFuncCalls); + + auto regs = array->GetRegionsName(); + for (auto& ref : realArrayRef) + { + auto regsRef = ref->GetRegionsName(); + for (auto& reg : regsRef) + { + if (regs.count(reg) == 0) + { + array->SetRegionPlace(reg); + modified = true; + } + } + + } + } + } + } + + bool hasNonDefaultReg = false; + for (auto& elem : parallelRegions) + { + string regName = elem->GetName(); + convertToLower(regName); + if (regName != "default") + hasNonDefaultReg = true; + } + + if (hasNonDefaultReg) + { + for (auto array : declaredArrays) + { + if (array.second.first->GetRegionsName().size() == 0) + array.second.first->SetDistributeFlag(DIST::NO_DISTR); + else if (array.second.first->GetRegionsName().size() == 1) + { + string regName = *array.second.first->GetRegionsName().begin(); + convertToLower(regName); + if (regName == "default") + array.second.first->SetDistributeFlag(DIST::NO_DISTR); + } + } + } } \ No newline at end of file diff --git a/src/ParallelizationRegions/ParRegions_func.h b/src/ParallelizationRegions/ParRegions_func.h index d1ac9b8..1cc15df 100644 --- a/src/ParallelizationRegions/ParRegions_func.h +++ b/src/ParallelizationRegions/ParRegions_func.h @@ -10,3 +10,7 @@ int printParalleRegions(const char *fileName, std::vector ®i bool buildGraphFromUserDirectives(const std::vector &userDvmAlignDirs, DIST::GraphCSR &G, DIST::Arrays &allArrays, const std::map> &arrayLinksByFuncCalls, const std::set& alignedArrays, std::set& addedArrays, const std::map>& funcsByFile); void clearRegionStaticData(); void calculateLinesOfCode(std::vector &allRegions); + +void propagateRegionInfo(std::map, std::pair>& declaredArrays, + const std::map>& arrayLinksByFuncCall, + const std::vector& parallelRegions); diff --git a/src/ParallelizationRegions/merge_regions.cpp b/src/ParallelizationRegions/merge_regions.cpp new file mode 100644 index 0000000..ed3a5dc --- /dev/null +++ b/src/ParallelizationRegions/merge_regions.cpp @@ -0,0 +1,588 @@ +#include "leak_detector.h" + +#include +#include +#include "merge_regions.h" +#include "../DirectiveProcessing/directive_parser.h" + +using std::map; +using std::set; +using std::pair; +using std::string; +using std::vector; + +static string getNonDefaultRegion(DIST::Array *a) +{ + string result; + + if (!a) + return result; + + for (const auto ®_name : a->GetRegionsName()) + { + if (reg_name != "default") + { + if (!result.empty()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + result = reg_name; + } + } + + return result; +} + +static bool hasSameSizes(DIST::Array *a, DIST::Array *b) +{ + for (auto *array : {a, b}) + { + for (const auto &p : array->GetSizes()) + { + if (p.first < 0 || p.second < 0) + return false; + } + } + + return a->GetSizes() == b->GetSizes() && a->GetTypeSize() == b->GetTypeSize(); +} + +static bool checkSimilarTemplates(vector ®ions, + const map &new_region_mapping) +{ + // new region -> old regions + map> new_region_inverse_mapping; + for (const auto &p : new_region_mapping) + new_region_inverse_mapping[p.second].insert(p.first); + + for (const auto &new_reg : new_region_inverse_mapping) + { + DIST::Array *template_array = nullptr; + string first_reg_name; + + for (const auto &old_region_name : new_reg.second) + { + auto *old_reg = getRegionByName(regions, old_region_name); + + if (!old_reg) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + const auto &distr_rules = old_reg->GetDataDir().GetDistrRules(); + if (distr_rules.size() != 1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto *current_template = distr_rules.front().first; + + if (template_array) + { + if (!hasSameSizes(template_array, current_template)) + { + __spf_print(1, "Templates of %s and %s has different sizes\n", + first_reg_name.c_str(), + old_region_name.c_str()); + + return false; + } + // else everything OK + } + else + { + template_array = current_template; + first_reg_name = old_region_name; + } + } + } + + return true; +} + +static bool hasSameAlignment(const std::set &align_a, + const std::set &align_b) +{ + if (align_a.size() != 1 || align_b.size() != 1) + return false; + + const auto *rule_a = *align_a.begin(); + const auto *rule_b = *align_b.begin(); + + if (rule_a->alignRule != rule_b->alignRule) + return false; + + return true; +} + +static void printExpr(SgExpression *e, string pad) +{ + if (!e) + return; + + __spf_print(1, "%s%d: %s\n", pad.c_str(), e->variant(), e->unparse()); + + printExpr(e->lhs(), pad + " "); + printExpr(e->rhs(), pad + " "); +} + +static pair, SgSymbol *> generateDeclaration(const string &array_name, const string &common_block_name, + const vector> &sizes, SgType *type, SgStatement *scope) +{ + auto *array_symbol = new SgSymbol(VARIABLE_NAME, array_name.c_str(), new SgType(T_ARRAY), scope); + + auto *decl = new SgDeclarationStatement(VAR_DECL); + + decl->setExpression(1, new SgTypeExp(*type)); + + SgExpression *subs = new SgExprListExp(); + + auto *array_ref = new SgArrayRefExp(*array_symbol, *subs); + + for (int i = 0; i < sizes.size(); i++) + { + const auto &p = sizes[i]; + auto *d = new SgExpression(DDOT, new SgValueExp(p.first), new SgValueExp(p.second)); + subs->setLhs(d); + + if (i + 1 < sizes.size()) + { + subs->setRhs(new SgExprListExp()); + subs = subs->rhs(); + } + } + + decl->setExpression(0, array_ref); + + auto comm = new SgStatement(COMM_STAT); + + comm->setExpression(0, new SgExpression(COMM_LIST, + new SgVarRefExp(array_symbol), + NULL, + new SgSymbol(COMMON_NAME, common_block_name.c_str()))); + + return {{decl, comm}, array_symbol}; +} + +static SgExpression* findExprWithVariant(SgExpression* exp, int variant) +{ + if (exp) + { + if (exp->variant() == variant) + return exp; + + auto *l = findExprWithVariant(exp->lhs(), variant); + if (l) + return l; + + auto *r = findExprWithVariant(exp->rhs(), variant); + if (r) + return r; + } + + return NULL; +} + +static SgType* GetArrayType(DIST::Array *array) +{ + if (!array) + return NULL; + + for (const auto& decl_place : array->GetDeclInfo()) + { + if (SgFile::switchToFile(decl_place.first) != -1) + { + auto* decl = SgStatement::getStatementByFileAndLine(decl_place.first, decl_place.second); + if (decl) + { + for (int i = 0; i < 3; i++) + { + auto* found_type = isSgTypeExp(findExprWithVariant(decl->expr(i), TYPE_OP)); + if (found_type) + return found_type->type(); + } + } + } + } + + return NULL; +} + +static SgSymbol *insertDeclIfNeeded(const string &array_name, + const string &common_block_name, + DIST::Array *example_array, + FuncInfo *dest, + map> &inserted_arrays) +{ + auto *type = GetArrayType(example_array); + + if (!type) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + if (SgFile::switchToFile(dest->fileName) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto &by_func = inserted_arrays[dest]; + auto it = by_func.find(array_name); + + if (it != by_func.end()) + return it->second; + + SgStatement *st = dest->funcPointer; + + auto *end = st->lastNodeOfStmt(); + + st = st->lexNext(); + + while (st != end && !isSgExecutableStatement(st)) + { + st = st->lexNext(); + } + + auto generated = generateDeclaration(array_name, common_block_name, + example_array->GetSizes(), + type, dest->funcPointer); + for (auto *new_stmt : generated.first) + st->insertStmtBefore(*new_stmt, *dest->funcPointer); + + by_func[array_name] = generated.second; + + return generated.second; +} + +static pair createNewArray(DIST::Array *example_array, const string &base_name, + const map> &allFuncInfo, + map> &inserted_arrays) +{ + auto common_block_name = base_name + "_merge_r"; + auto array_name = base_name; + + for (const auto &by_file : allFuncInfo) + { + for (auto *func_info : by_file.second) + { + if (func_info->isMain) + { + insertDeclIfNeeded( + array_name, + common_block_name, + example_array, + func_info, + inserted_arrays); + } + } + } + + return std::make_pair(array_name, common_block_name); +} + +static void replaceArrayRec(SgExpression *e, + const set &arrays_to_replace, + SgSymbol **func_symbol_hint, + const pair &replace_by, + DIST::Array *example_array, + FuncInfo *func, + map> &inserted_arrays) +{ + if (!e) + return; + + if (isArrayRef(e) && arrays_to_replace.find(e->symbol()->identifier()) != arrays_to_replace.end()) + { + if (!(*func_symbol_hint)) + { + *func_symbol_hint = insertDeclIfNeeded( + replace_by.first, replace_by.second, + example_array, + func, + inserted_arrays); + } + + e->setSymbol(*func_symbol_hint); + } + + replaceArrayRec( + e->lhs(), + arrays_to_replace, + func_symbol_hint, + replace_by, + example_array, + func, + inserted_arrays); + + replaceArrayRec( + e->rhs(), + arrays_to_replace, + func_symbol_hint, + replace_by, + example_array, + func, + inserted_arrays); +} + +static void replaceRegion(SgStatement* st, const map &new_region_mapping) +{ + if (!st) + return; + + if(isSPF_stat(st) && st->variant() == SPF_PARALLEL_REG_DIR) + { + auto it = new_region_mapping.find(st->symbol()->identifier()); + + if (it != new_region_mapping.end()) + st->setSymbol(*(new SgSymbol(CONST_NAME, it->second.c_str()))); + } +} + +void mergeRegions(vector ®ions, const map> &allFuncInfo) +{ + for (const auto *region : regions) + { + __spf_print(1, "region %s\n", region->GetName().c_str()); + + const auto &dirs = region->GetDataDir(); + + __spf_print(1, " distr rules: %d\n", dirs.distrRules.size()); + + const auto ¤tVariant = region->GetCurrentVariant(); + + int distr_idx = 0; + for (const auto &distr : dirs.distrRules) + { + const auto &dist_rule = distr.second.back().distRule; + + string sizes; + for (const auto &p : distr.first->GetSizes()) + { + if (!sizes.empty()) + sizes.push_back(','); + + sizes += std::to_string(p.first) + ":" + std::to_string(p.second); + } + + __spf_print(1, " DIST %s(%s)", distr.first->GetName().c_str(), sizes.c_str()); + for (const auto &dim : dist_rule) + __spf_print(1, " %c", dim == dist::BLOCK ? 'B' : '*'); + + __spf_print(1, "\n"); + distr_idx++; + } + + __spf_print(1, " align rules: %d\n", dirs.alignRules.size()); + + for (const auto &align : dirs.alignRules) + { + string sub_a, sub_b; + + int i = 0; + for (const auto coefs : align.alignRule) + { + if (!sub_a.empty()) + sub_a.push_back(','); + + sub_a += std::to_string(coefs.first) + "*i" + + std::to_string(i) + "+" + std::to_string(coefs.second); + + i++; + } + + for (const auto coefs : align.alignRuleWith) + { + if (!sub_b.empty()) + sub_b.push_back(','); + + sub_b += std::to_string(coefs.second.first) + "*i" + + std::to_string(coefs.first) + "+" + std::to_string(coefs.second.second); + } + + __spf_print(1, " ALIGN %s(%s) WITH %s(%s)\n", + align.alignArray->GetName().c_str(), sub_a.c_str(), + align.alignWith->GetName().c_str(), sub_b.c_str()); + } + } + + // parse directives + + // new array name -> current arrays + map> arrays_to_merge; + map> array_alignment; + + for (const auto &by_file : allFuncInfo) + { + const auto current_file_name = by_file.first; + + if (SgFile::switchToFile(current_file_name) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (auto *func_info : by_file.second) + { + SgStatement *curr_stmt = func_info->funcPointer; + if (!curr_stmt) + continue; + + auto *stmt_end = curr_stmt->lastDeclaration(); + if (!stmt_end) + continue; + + stmt_end = stmt_end->lexNext(); + + for (; curr_stmt && curr_stmt != stmt_end; curr_stmt = curr_stmt->lexNext()) + { + auto attributes = getAttributes(curr_stmt, set{SPF_TRANSFORM_DIR}); + + for (auto& attr : attributes) + { + pair parsed_mapping = { "", "" }; + const auto empty = parsed_mapping; + fillMergeArraysFromComment(new Statement(attr), parsed_mapping); + + if (parsed_mapping != empty) + { + auto* found_array = getArrayFromDeclarated(curr_stmt, parsed_mapping.first); + if (found_array) + { + arrays_to_merge[parsed_mapping.second].insert(found_array); + array_alignment[found_array] = {}; + } + } + } + } + } + } + + // find alignment rules for array + + for (const auto *region : regions) + { + const auto &dirs = region->GetDataDir(); + + for (const auto &align : dirs.alignRules) + { + auto it = array_alignment.find(align.alignArray); + + if (it != array_alignment.end()) + it->second.insert(&align); + } + } + + // old region -> new region + map new_region_mapping; + + // new array -> new region + map arrays_new_region_mapping; + vector created_region_names; + + for (const auto &by_new_array : arrays_to_merge) + { + string new_region_name; + for (auto *current_array : by_new_array.second) + { + auto current_array_region = getNonDefaultRegion(current_array); + auto it = new_region_mapping.find(current_array_region); + if (it != new_region_mapping.end()) + { + if (new_region_name.empty()) + new_region_name = it->second; + else if (new_region_name != it->second) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + } + } + + if (new_region_name.empty()) + { + new_region_name = "merged_reg_" + std::to_string(created_region_names.size()); + created_region_names.push_back(new_region_name); + } + + for (auto *current_array : by_new_array.second) + { + auto current_array_region = getNonDefaultRegion(current_array); + new_region_mapping[current_array_region] = new_region_name; + } + + arrays_new_region_mapping[by_new_array.first] = new_region_name; + } + + if (!checkSimilarTemplates(regions, new_region_mapping)) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + map> inserted_arrays; + + for (const auto &by_dest_array : arrays_to_merge) + { + const auto ©_arrays = by_dest_array.second; + + if (copy_arrays.empty()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto *first_element = *copy_arrays.begin(); + auto first_elem_rules_it = array_alignment.find(first_element); + + if (first_elem_rules_it == array_alignment.end()) + continue; + + const auto &first_elem_rules = first_elem_rules_it->second; + + for (auto *array_to_merge : copy_arrays) + { + auto array_rules_it = array_alignment.find(array_to_merge); + + if (array_rules_it == array_alignment.end()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + const auto &array_rules = array_rules_it->second; + + if (!hasSameSizes(array_to_merge, first_element) || !hasSameAlignment(first_elem_rules, array_rules)) + { + __spf_print(1, "Arrays %s and %s has different sizes or align rules\n", + array_to_merge->GetName().c_str(), + first_element->GetName().c_str()); + + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + } + } + + __spf_print(1, "merge into %s (%s):\n", by_dest_array.first.c_str(), arrays_new_region_mapping[by_dest_array.first].c_str()); + for (auto *array_to_merge : copy_arrays) + __spf_print(1, "%s\n", array_to_merge->GetName().c_str()); + + auto created_array_info = createNewArray(first_element, by_dest_array.first, allFuncInfo, inserted_arrays); + + set arrays_to_replace; + for (auto *array_to_merge : copy_arrays) + arrays_to_replace.insert(array_to_merge->GetShortName()); + + for (const auto &by_file : allFuncInfo) + { + if (SgFile::switchToFile(by_file.first) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (auto *func_info : by_file.second) + { + SgSymbol *func_symbol_hint = nullptr; + SgStatement *st = func_info->funcPointer; + + auto *func_end = st->lastNodeOfStmt(); + + st = st->lexNext(); + + while (st && !isSgExecutableStatement(st) && st != func_end) + st = st->lexNext(); + + while (st && st != func_end) + { + for (int i = 0; i < 3; i++) + { + replaceArrayRec( + st->expr(i), + arrays_to_replace, + &func_symbol_hint, + created_array_info, + first_element, + func_info, + inserted_arrays); + } + + replaceRegion(st, new_region_mapping); + + st = st->lexNext(); + } + } + } + } +} \ No newline at end of file diff --git a/src/ParallelizationRegions/merge_regions.h b/src/ParallelizationRegions/merge_regions.h new file mode 100644 index 0000000..6ecee53 --- /dev/null +++ b/src/ParallelizationRegions/merge_regions.h @@ -0,0 +1,8 @@ +#include "../GraphCall/graph_calls.h" +#include "ParRegions.h" + +#include +#include +#include + +void mergeRegions(std::vector ®ions, const std::map> &allFuncInfo); \ No newline at end of file diff --git a/src/ParallelizationRegions/resolve_par_reg_conflicts.cpp b/src/ParallelizationRegions/resolve_par_reg_conflicts.cpp index 0f2e922..62b9acb 100644 --- a/src/ParallelizationRegions/resolve_par_reg_conflicts.cpp +++ b/src/ParallelizationRegions/resolve_par_reg_conflicts.cpp @@ -19,6 +19,7 @@ #include "SgUtils.h" #include "expr_transform.h" #include "FunctionPurifying/function_purifying.h" +#include "uniq_name_creator.h" using std::map; using std::pair; @@ -71,7 +72,7 @@ static bool isSPF_reg(SgStatement *st) return st->variant() == SPF_PARALLEL_REG_DIR || st->variant() == SPF_END_PARALLEL_REG_DIR; } -static const vector getArraySynonyms(DIST::Array *array) +const vector getArraySynonyms(DIST::Array *array) { auto arrayBlock = allUsedCommonArrays.find(array); if (arrayBlock == allUsedCommonArrays.end()) @@ -127,15 +128,16 @@ static string getStringDeclaration(SgSymbol *symb) return decl; } -static void insertStringDeclarations(SgStatement *insertPlace, DIST::Array *array) +static void insertStringDeclarations(SgStatement *insertPlace, DIST::Array *array, UniqueNameCreator& unique_name_creator) { auto varsOnPos = getArraySynonyms(array); if (varsOnPos.size() && varsOnPos[0]->getName() == array->GetShortName()) { + string newArrName, commName; + unique_name_creator.GetUniqueName(array, newArrName, commName); SgSymbol *varSymb = varsOnPos[0]->getSymbol(); string varName = varSymb->identifier(); - string newName = varName + "_c"; - varSymb->changeName(newName.c_str()); + varSymb->changeName(newArrName.c_str()); string decl = getStringDeclaration(varsOnPos[0]->getSymbol()); varSymb->changeName(varName.c_str()); insertPlace->addComment(decl.c_str()); @@ -662,12 +664,11 @@ static void replaceFuncCalls(const ParallelRegionLines &lines, const map> createdCommonBlocks; // file -> array -> new common statement static map>> createdCommonArrays; // file -> array -> (orig, copy) -static SgStatement* createCommonBlock(SgFile *file, DIST::Array *array) +static SgStatement* createCommonBlock(SgFile *file, DIST::Array *array, UniqueNameCreator& unique_name_creator) { - auto varsOnPos = getArraySynonyms(array); - if (!varsOnPos.size()) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + string newArrName, commBlockName; + unique_name_creator.GetUniqueName(array, newArrName, commBlockName); string fileName = file->filename(); if (SgFile::switchToFile(fileName) != -1) @@ -683,7 +684,6 @@ static SgStatement* createCommonBlock(SgFile *file, DIST::Array *array) // creating new common-block statement //TODO: consistence with declaration //string commBlockName = checkSymbNameAndCorrect(array->GetShortName() + "_r"); - string commBlockName = array->GetShortName() + "_r"; SgStatement *commDecl = new SgStatement(COMM_STAT); SgSymbol *commSymb = new SgSymbol(VARIABLE_NAME, commBlockName.c_str()); @@ -705,7 +705,6 @@ static SgStatement* createCommonBlock(SgFile *file, DIST::Array *array) { //TODO: consistence with declaration //string newArrName = checkSymbNameAndCorrect(varsOnPos[0]->getName() + "_c"); - string newArrName = varsOnPos[0]->getName() + "_c"; newArrSymb = new SgSymbol(VARIABLE_NAME, newArrName.c_str(), file->firstStatement()); SgType *type = new SgType(T_ARRAY); @@ -751,7 +750,7 @@ static SgStatement* createCommonBlock(SgFile *file, DIST::Array *array) // func -> arrays; funcs where new common statement inserted static map> insertedCommonBlocks; -static void insertCommonBlock(FuncInfo *func, DIST::Array *array) +static void insertCommonBlock(FuncInfo *func, DIST::Array *array, UniqueNameCreator& unique_name_creator) { SgFile *file = func->funcPointer->GetOriginal()->getFile(); SgStatement *insertPlace = NULL; @@ -767,7 +766,7 @@ static void insertCommonBlock(FuncInfo *func, DIST::Array *array) if (!insertPlace) insertPlace = func->funcPointer->GetOriginal(); - SgStatement *commDecl = createCommonBlock(file, array); + SgStatement *commDecl = createCommonBlock(file, array, unique_name_creator); SgStatement *copyDecl = commDecl->copyPtr(); auto st = insertPlace->controlParent(); @@ -779,7 +778,7 @@ static void insertCommonBlock(FuncInfo *func, DIST::Array *array) insertPlace->lexNext()->setlineNumber(nextLine); // create declaration via comment - insertStringDeclarations(insertPlace->lexNext(), array); + insertStringDeclarations(insertPlace->lexNext(), array, unique_name_creator); } // file -> lines -> arrays; lines where arrays copying is inserted @@ -1097,6 +1096,7 @@ pair copyArray(const pair &place, static void copyFunction(ParallelRegion *region, FuncInfo *func, const map &funcMap, + UniqueNameCreator& unique_name_creator, const string &suffix = "") { if (SgFile::switchToFile(func->fileName) != -1) @@ -1146,14 +1146,14 @@ static void copyFunction(ParallelRegion *region, if (origStat->variant() == COMM_STAT) { for (auto &arrayBlock : allUsedCommonArrays) - createCommonBlock(file, arrayBlock.first); + createCommonBlock(file, arrayBlock.first, unique_name_creator); auto usedCommonArrays = region->GetUsedCommonArrays().find(func); if (usedCommonArrays != region->GetUsedCommonArrays().end()) { for (auto &arrayLines : usedCommonArrays->second) { - SgStatement *commDecl = createCommonBlock(file, arrayLines.first); + SgStatement *commDecl = createCommonBlock(file, arrayLines.first, unique_name_creator); SgStatement *copyDecl = commDecl->copyPtr(); while (!isSgExecutableStatement(copyStat) || isSPF_stat(copyStat)) @@ -1163,7 +1163,7 @@ static void copyFunction(ParallelRegion *region, copyStat->insertStmtAfter(*copyDecl, *copyStat->controlParent()); // making declaration of new common array symbol via comment through files - insertStringDeclarations(copyStat->lexNext(), arrayLines.first); + insertStringDeclarations(copyStat->lexNext(), arrayLines.first, unique_name_creator); } auto it = createdCommonArrays.find(file->filename()); @@ -1619,6 +1619,8 @@ int resolveParRegions(vector ®ions, const map funcMap; createMapOfFunc(allFuncInfo, funcMap); + UniqueNameCreator unique_name_creator(allFuncInfo); + if (sharedMemoryParallelization == 0) { map>> copied; @@ -1688,7 +1690,7 @@ int resolveParRegions(vector ®ions, const mapsecond.end() && arrayBlock.first->GetShortName() == varsOnPos[0]->getName()) { // need to insert common-block - insertCommonBlock(func, arrayBlock.first); + insertCommonBlock(func, arrayBlock.first, unique_name_creator); it->second.insert(arrayBlock.first); } } @@ -1781,7 +1783,7 @@ int resolveParRegions(vector ®ions, const mapsecond.end() && arrayBlock.first->GetShortName() == varsOnPos[0]->getName()) { // need to insert common-block - insertCommonBlock(func, arrayBlock.first); + insertCommonBlock(func, arrayBlock.first, unique_name_creator); it->second.insert(arrayBlock.first); } } @@ -1813,7 +1815,7 @@ int resolveParRegions(vector ®ions, const mapGetUsedCommonArrays().end()) { for (auto &arrayBlock : allUsedCommonArrays) - createCommonBlock(file, arrayBlock.first); + createCommonBlock(file, arrayBlock.first, unique_name_creator); auto it = insertedCommonBlocks.find(func); if (it == insertedCommonBlocks.end()) @@ -1825,7 +1827,7 @@ int resolveParRegions(vector ®ions, const mapsecond.end()) { // need to insert common-block - insertCommonBlock(func, arrayLines.first); + insertCommonBlock(func, arrayLines.first, unique_name_creator); it->second.insert(arrayLines.first); // replace common arrays to new common arrays in executable code section @@ -1858,7 +1860,7 @@ int resolveParRegions(vector ®ions, const mapcallRegions) if (regionId) - copyFunction(getRegionById(regions, regionId), func, funcMap, string("_r") + to_string(regionId)); + copyFunction(getRegionById(regions, regionId), func, funcMap, unique_name_creator, string("_r") + to_string(regionId)); } } } diff --git a/src/ParallelizationRegions/resolve_par_reg_conflicts.h b/src/ParallelizationRegions/resolve_par_reg_conflicts.h index cfaecbe..38e3fd7 100644 --- a/src/ParallelizationRegions/resolve_par_reg_conflicts.h +++ b/src/ParallelizationRegions/resolve_par_reg_conflicts.h @@ -21,4 +21,6 @@ std::pair copyArray(const std::pair& pla const std::string& suffix, std::string& filename, std::map>>& newDeclsToInclude, - std::map>>& copied); \ No newline at end of file + std::map>>& copied); + +const std::vector getArraySynonyms(DIST::Array* array); \ No newline at end of file diff --git a/src/ParallelizationRegions/uniq_name_creator.cpp b/src/ParallelizationRegions/uniq_name_creator.cpp new file mode 100644 index 0000000..6387d6e --- /dev/null +++ b/src/ParallelizationRegions/uniq_name_creator.cpp @@ -0,0 +1,98 @@ +#include "leak_detector.h" + +#include +#include +#include + +#include "SgUtils.h" +#include "uniq_name_creator.h" +#include "resolve_par_reg_conflicts.h" + +using namespace::std; + +static const string COMMON_ARRAY_SUFFIX = "_c"; +static const string COMMON_BLOCK_SUFFIX = "_r"; + +void UniqueNameCreator::GetSymbolsRec(SgExpression* exp, set& add_to) +{ + if (!exp) + return; + + if (isArrayRef(exp) && exp->symbol() && exp->symbol()->identifier()) + add_to.emplace(exp->symbol()->identifier()); + + GetSymbolsRec(exp->lhs(), add_to); + GetSymbolsRec(exp->rhs(), add_to); +} + +void UniqueNameCreator::FillDeclarations() +{ + allDeclarations.clear(); + auto* file_before = current_file; + + for (const auto& by_file : funcInfo) + { + if (SgFile::switchToFile(by_file.first) != -1) + { + for (const auto* by_func : by_file.second) + { + SgStatement* st = by_func->funcPointer; + + if (st) + st = st->lexNext(); + + while (st) + { + for (int i = 0; i < 3; i++) + GetSymbolsRec(st->expr(i), allDeclarations); + + st = st->lexNext(); + } + } + } + else + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + } + + SgFile::switchToFile(file_before->filename()); + declarationsAnalyzed = true; +} + +void UniqueNameCreator::GetUniqueName(DIST::Array* array, string& array_name, string& common_block_name) +{ + auto varsOnPos = getArraySynonyms(array); + if (!varsOnPos.size()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto array_plain_name = varsOnPos[0]->getName(); + + auto it = generatedNames.find(array); + if (it != generatedNames.end()) + { + array_name.assign(it->second.first); + common_block_name.assign(it->second.second); + return; + } + + if (!declarationsAnalyzed) + FillDeclarations(); + + int v = 1; + auto created_array_name = array_plain_name + COMMON_ARRAY_SUFFIX; + auto created_common_name = array_plain_name + COMMON_BLOCK_SUFFIX; + + while (allDeclarations.find(created_array_name) != allDeclarations.end() || + allDeclarations.find(created_common_name) != allDeclarations.end()) + { + created_array_name = array_plain_name + "_v" + std::to_string(v) + COMMON_ARRAY_SUFFIX; + created_common_name = array_plain_name + "_v" + std::to_string(v) + COMMON_BLOCK_SUFFIX; + v++; + } + + allDeclarations.insert(created_array_name); + allDeclarations.insert(created_common_name); + generatedNames.emplace(array, std::make_pair(created_array_name, created_common_name)); + + array_name.assign(created_array_name); + common_block_name.assign(created_common_name); +} diff --git a/src/ParallelizationRegions/uniq_name_creator.h b/src/ParallelizationRegions/uniq_name_creator.h new file mode 100644 index 0000000..d509371 --- /dev/null +++ b/src/ParallelizationRegions/uniq_name_creator.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include +#include "GraphCall/graph_calls.h" + +class UniqueNameCreator +{ + std::map> funcInfo; + std::set allDeclarations; + bool declarationsAnalyzed = false; + std::map> generatedNames; + + static void GetSymbolsRec(SgExpression* exp, std::set& add_to); + void FillDeclarations(); + +public: + UniqueNameCreator(const std::map>& allFuncInfo) + { + declarationsAnalyzed = false; + funcInfo = allFuncInfo; + } + + void GetUniqueName(DIST::Array* array, std::string& array_name, std::string& common_block_name); +}; diff --git a/src/PrivateAnalyzer/private_arrays_search.cpp b/src/PrivateAnalyzer/private_arrays_search.cpp index 95624f5..1cb044e 100644 --- a/src/PrivateAnalyzer/private_arrays_search.cpp +++ b/src/PrivateAnalyzer/private_arrays_search.cpp @@ -1,28 +1,31 @@ #include #include -#include -#include +#include #include #include #include #include +#include "CFGraph/CFGraph.h" +#include "Distribution/Array.h" +#include "errors.h" +#include "graph_loops.h" #include "private_arrays_search.h" #include "range_structures.h" #include "region.h" #include "SgUtils.h" -#include "graph_loops.h" -#include "CFGraph/CFGraph.h" +#include "Transformations/ArrayConstantPropagation/propagation.h" #include "utils.h" +#include "Utils/AstWrapper.h" using namespace std; -static unordered_set collapsed; +static set collapsed; -static void RemoveEmptyPoints(ArrayAccessingIndexes& container) +static void removeEmptyPoints(arrayAccessingIndexes& container) { - ArrayAccessingIndexes resultContainer; - unordered_set toRemove; + arrayAccessingIndexes resultContainer; + set toRemove; for (auto& [arrayName, accessingSet] : container) { @@ -33,10 +36,9 @@ static void RemoveEmptyPoints(ArrayAccessingIndexes& container) points.push_back(arrayPoint); } - if (points.size() < accessingSet.GetElements().size() && !points.empty()) + if (!points.empty()) resultContainer[arrayName] = points; - - if (points.empty()) + else toRemove.insert(arrayName); } @@ -47,12 +49,13 @@ static void RemoveEmptyPoints(ArrayAccessingIndexes& container) container[arrayName] = accessingSet; } -static void Collapse(Region* region) +static void collapse(Region* region) { if (region->getBasickBlocks().empty()) return; bool firstRegion = true; + int blockCount = 0; for (Region* basickBlock : region->getBasickBlocks()) { if (basickBlock->getNextRegions().empty()) @@ -64,7 +67,7 @@ static void Collapse(Region* region) } else { - unordered_set toErease; + set toErease; for (auto& [arrayName, arrayRanges] : region->array_def) { if (basickBlock->array_out.find(arrayName) != basickBlock->array_out.end()) @@ -84,11 +87,15 @@ static void Collapse(Region* region) RegionInstruction instruction; instruction.def = move(region->array_def); - + arrayAccessingIndexes recursivePriv; for (auto& byBlock : region->getBasickBlocks()) { + if (!byBlock->array_priv.empty()) + recursivePriv = byBlock->array_priv; for (auto& instruction : byBlock->instructions) { + if (!instruction.def.empty() || !instruction.use.empty()) + blockCount++; for (auto& [arrayName, _] : instruction.use) { AccessingSet diff = instruction.use[arrayName].Diff(instruction.in[arrayName]); @@ -97,7 +104,7 @@ static void Collapse(Region* region) } } - ArrayAccessingIndexes useUnionB; + arrayAccessingIndexes useUnionB; for (auto& byBlock : region->getBasickBlocks()) for (auto& instruction : byBlock->instructions) for (auto& [arrayName, _] : instruction.use) @@ -120,72 +127,13 @@ static void Collapse(Region* region) region->addNextRegion(nextBlock); } region->instructions.push_back(instruction); - + if (blockCount == 1 && !recursivePriv.empty()) + region->array_priv = move(recursivePriv); } -static void SolveDataFlowIteratively(Region* DFG) +static void solveForBasickBlock(Region* block) { - auto blocks = DFG->getBasickBlocks(); - std::unordered_set worklist(blocks.begin(), blocks.end()); - do - { - Region* b = *worklist.begin(); - ArrayAccessingIndexes newIn; - bool flagFirst = true; - for (Region* prevBlock : b->getPrevRegions()) - { - if (flagFirst) - { - newIn = prevBlock->array_out; - flagFirst = false; - } - else - { - if (prevBlock->array_out.empty()) - { - newIn.clear(); - break; - } - - for (const auto& [arrayName, accessSet] : prevBlock->array_out) - { - if (newIn.find(arrayName) != newIn.end()) - newIn[arrayName] = newIn[arrayName].Intersect(accessSet); - else - newIn[arrayName] = AccessingSet(); - } - } - } - - b->array_in = move(newIn); - ArrayAccessingIndexes newOut; - - if (b->array_def.empty()) - newOut = b->array_in; - else if (b->array_in.empty()) - newOut = b->array_def; - else - { - for (auto& [arrayName, accessSet] : b->array_def) - { - if (newOut.find(arrayName) != newOut.end()) - newOut[arrayName] = b->array_def[arrayName].Union(b->array_in[arrayName]); - else - newOut[arrayName] = accessSet; - } - } - - /* can not differ */ - if (newOut != b->array_out) - b->array_out = newOut; - else - worklist.erase(b); - } while (!worklist.empty()); -} - -static void SolveForBasickBlock(Region* block) -{ - ArrayAccessingIndexes newIn; + arrayAccessingIndexes newIn; bool flagFirst = true; for (Region* prevBlock : block->getPrevRegions()) { @@ -224,7 +172,7 @@ static void SolveForBasickBlock(Region* block) if (i > 0) instruction.in = block->instructions[i - 1].out; - ArrayAccessingIndexes newOut; + arrayAccessingIndexes newOut; if (instruction.def.empty()) newOut = instruction.in; else if (instruction.in.empty()) @@ -241,9 +189,7 @@ static void SolveForBasickBlock(Region* block) for (auto& [arrayName, accessSet] : instruction.in) { if (newOut.find(arrayName) == newOut.end()) - { newOut[arrayName] = accessSet; - } } } @@ -253,35 +199,35 @@ static void SolveForBasickBlock(Region* block) block->array_out = block->instructions.back().out; } -static void SolveDataFlowTopologically(Region* DFG) +static void solveDataFlowTopologically(Region* DFG) { for (Region* b : DFG->getBasickBlocks()) { collapsed.insert(b); - SolveForBasickBlock(b); + solveForBasickBlock(b); } } -static void SolveDataFlow(Region* DFG) +static void solveDataFlow(Region* DFG) { if (!DFG) return; + for (Region* subRegion : DFG->getSubRegions()) { - SolveDataFlow(subRegion); + solveDataFlow(subRegion); DFG->addBasickBlocks(subRegion); } vector& blocks = DFG->getBasickBlocks(); auto pos = remove_if(blocks.begin(), blocks.end(), [](Region* r) { return collapsed.find(r) != collapsed.end(); }); blocks.erase(pos, blocks.end()); - TopologySort(DFG->getBasickBlocks(), DFG->getHeader()); - SolveDataFlowTopologically(DFG); - Collapse(DFG); + topologySort(DFG->getBasickBlocks(), DFG->getHeader()); + solveDataFlowTopologically(DFG); + collapse(DFG); } static bool getArrayDeclaredDimensions(SgArrayRefExp* arrayRef, vector& declaredDims) { - declaredDims.clear(); if (!arrayRef || !arrayRef->symbol() || !isSgArrayType(arrayRef->symbol()->type())) return false; SgArrayType* arrayType = (SgArrayType*)arrayRef->symbol()->type(); @@ -290,54 +236,103 @@ static bool getArrayDeclaredDimensions(SgArrayRefExp* arrayRef, vector { SgExpression* sizeExpr = arrayType->sizeInDim(i); SgConstantSymb* constValSymb = isSgConstantSymb(sizeExpr->symbol()); - string strDimLength; + SgSubscriptExp* subscriptExpr = isSgSubscriptExp(sizeExpr); + uint64_t dimLength; if (sizeExpr && sizeExpr->variant() == INT_VAL) - strDimLength = sizeExpr->unparse(); + dimLength = stol(sizeExpr->unparse()); else if (constValSymb) - strDimLength = constValSymb->constantValue()->unparse(); + dimLength = stol(constValSymb->constantValue()->unparse()); + else if (subscriptExpr) + dimLength = stol(subscriptExpr->rhs()->unparse()) - stol(subscriptExpr->lhs()->unparse()); else return false; - if (strDimLength == "0") + if (dimLength == 0) return false; - declaredDims.push_back((uint64_t)stoi(strDimLength)); + declaredDims.push_back(dimLength); } return true; } -static bool CheckDimensionLength(const AccessingSet& array) +static DIST::Array* getDistArrayBySymbol(SgSymbol* arrSym, const map, pair>& declaredArrays) +{ + if (!arrSym) + return nullptr; + for (auto& [key, val] : declaredArrays) + { + DIST::Array* distArr = val.first; + if (!distArr) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + Symbol* declSym = distArr->GetDeclSymbol(); + if (!declSym) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + SgSymbol* sgDecl = declSym->GetOriginal(); + if (sgDecl && isEqSymbols(sgDecl, arrSym)) + return distArr; + } + return nullptr; +} + +static bool checkDimensionLength(const AccessingSet& array, const map, pair>& declaredArrays) { if (array.GetElements().empty()) return false; size_t dimCount = array.GetElements()[0].size(); SgArrayRefExp* arrayRef = array.GetElements()[0][0].array; - if (!arrayRef) + if (!arrayRef || !arrayRef->symbol()) return false; - vector declaredDims(dimCount); - if (!getArrayDeclaredDimensions(arrayRef, declaredDims)) - return false; - vector testArray(dimCount); - for (size_t i = 0; i < dimCount; i++) - { - testArray[i] = { 1, 1, declaredDims[i], nullptr }; - } - AccessingSet diff = AccessingSet({ testArray }).Diff(array); - return diff.GetElements().empty(); + vector declaredDims; + declaredDims.reserve(dimCount); + + DIST::Array* distArr = getDistArrayBySymbol(arrayRef->symbol(), declaredArrays); + if (distArr && distArr->GetDimSize() == (int)dimCount) + { + const auto& sizes = distArr->GetSizes(); + bool valid = true; + for (size_t i = 0; i < dimCount && valid; ++i) + { + int lo = sizes[i].first; + int hi = sizes[i].second; + if (lo > hi) + valid = false; + else + declaredDims.push_back((uint64_t)(hi - lo + 1)); + } + if (valid && declaredDims.size() == dimCount) + { + vector testArray(dimCount); + for (size_t i = 0; i < dimCount; i++) + testArray[i] = { 1, 1, declaredDims[i], nullptr }; + return AccessingSet({ testArray }).Diff(array).GetElements().empty(); + } + } + + return false; } - -static void AddPrivateArraysToLoop(LoopGraph* loop, const ArrayAccessingIndexes& privates, set& insertedPrivates) +static int addPrivateArraysToLoop(LoopGraph* loop, const arrayAccessingIndexes& privates, set& insertedPrivates, + map>& SPF_messages, + const map, pair>& declaredArrays) { SgStatement* spfStat = new SgStatement(SPF_ANALYSIS_DIR); spfStat->setlineNumber(loop->loop->lineNumber()); spfStat->setFileName(loop->loop->fileName()); SgExpression* toAdd = new SgExpression(EXPR_LIST, new SgExpression(ACC_PRIVATE_OP), NULL, NULL); set arraysToInsert; - for (const auto& [_, accessingSet] : privates) + for (const auto& [arrayName, accessingSet] : privates) { - if (!CheckDimensionLength(accessingSet)) + int idx = arrayName.find('%'); + string name = (idx != -1 ? arrayName.substr(idx+1) : arrayName); + if (!checkDimensionLength(accessingSet, declaredArrays)) + { + wstring messageE, messageR; + __spf_printToLongBuf(messageE, L"Private array '%s' was skipped because dimension lengths are inconsistent", to_wstring(name).c_str()); + __spf_printToLongBuf(messageR, R159, to_wstring("array " + name + " has inconsistent dimension lengths").c_str()); + SPF_messages[loop->loop->fileName()].push_back(Messages(WARR, loop->loop->lineNumber(), messageR, messageE, 1029)); continue; + } + for (const auto& arrayElement : accessingSet.GetElements()) { if (arrayElement.empty()) @@ -372,12 +367,18 @@ static void AddPrivateArraysToLoop(LoopGraph* loop, const ArrayAccessingIndexes& } } -void FindPrivateArrays(map>& loopGraph, map>& FullIR, set& insertedPrivates) +int findPrivateArrays(map>& loopGraph, map>& FullIR, + set& insertedPrivates, + map>& SPF_messages, + const map, pair>& declaredArrays) { - map result; + map result; for (const auto& [fileName, loops] : loopGraph) { - SgFile::switchToFile(fileName); + if (SgFile::switchToFile(fileName) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + for (const auto& loop : loops) { if (!loop->isFor()) @@ -391,21 +392,53 @@ void FindPrivateArrays(map>& loopGraph, mapfileName == fileName && funcInfo->funcPointer->GetOriginal() == search_func) { - Region* loopRegion = new Region(loop, blocks); + Region* loopRegion = nullptr; + try + { + loopRegion = new Region(loop, blocks); + } + catch (...) + { + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + } + if (loopRegion->getBasickBlocks().size() <= 1) { - delete(loopRegion); + delete loopRegion; continue; } - SolveDataFlow(loopRegion); - RemoveEmptyPoints(loopRegion->array_priv); + + solveDataFlow(loopRegion); + removeEmptyPoints(loopRegion->array_priv); result[loop] = loopRegion->array_priv; - delete(loopRegion); + delete loopRegion; } } if (result.find(loop) != result.end() && !result[loop].empty()) - AddPrivateArraysToLoop(loop, result[loop], insertedPrivates); + addPrivateArraysToLoop(loop, result[loop], insertedPrivates, SPF_messages, declaredArrays); } } + + for (const auto& [loop, accesing] : result) + { + if (accesing.size()) + { + __spf_print(1, "found for loop on line %d in file %s\n", loop->lineNum, loop->fileName.c_str()); + for (const auto& [name, accesingSet] : accesing) + { + const auto& byDimention = accesingSet.GetElements(); + __spf_print(1, " for array %s with dimention %d\n", name.c_str(), byDimention.size()); + + for (int z = 0; z < byDimention.size(); ++z) + { + __spf_print(1, " dim %d (start, step, tripCount):\n", z); + for (auto& elem : byDimention[z]) + __spf_print(1, " [%ld %ld %ld]\n", elem.start, elem.step, elem.tripCount); + } + } + } + } + + return insertedPrivates.size(); } \ No newline at end of file diff --git a/src/PrivateAnalyzer/private_arrays_search.h b/src/PrivateAnalyzer/private_arrays_search.h index ca5da48..f784fe0 100644 --- a/src/PrivateAnalyzer/private_arrays_search.h +++ b/src/PrivateAnalyzer/private_arrays_search.h @@ -3,11 +3,12 @@ #include #include #include -#include #include "range_structures.h" #include "graph_loops.h" #include "CFGraph/CFGraph.h" -void FindPrivateArrays(std::map>& loopGraph, std::map>& FullIR, std::set& insertedPrivates); -std::pair> GetBasicBlocksForLoop(const LoopGraph* loop, const std::vector blocks); +int findPrivateArrays(std::map>& loopGraph, std::map>& FullIR, std::set& insertedPrivates, + std::map>& SPF_messages, + const std::map, std::pair>& declaredArrays); diff --git a/src/PrivateAnalyzer/range_structures.cpp b/src/PrivateAnalyzer/range_structures.cpp index f8be53d..eeb0085 100644 --- a/src/PrivateAnalyzer/range_structures.cpp +++ b/src/PrivateAnalyzer/range_structures.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include "utils.h" @@ -8,7 +8,7 @@ using namespace std; -static vector FindParticularSolution(const ArrayDimension& dim1, const ArrayDimension& dim2) +static vector findParticularSolution(const ArrayDimension& dim1, const ArrayDimension& dim2) { for (uint64_t i = 0; i < dim1.tripCount; i++) { @@ -24,9 +24,9 @@ static vector FindParticularSolution(const ArrayDimension& dim1, const } /* dim1 /\ dim2 */ -static ArrayDimension* DimensionIntersection(const ArrayDimension& dim1, const ArrayDimension& dim2) +static ArrayDimension* dimensionIntersection(const ArrayDimension& dim1, const ArrayDimension& dim2) { - vector partSolution = FindParticularSolution(dim1, dim2); + vector partSolution = findParticularSolution(dim1, dim2); if (partSolution.empty()) return NULL; @@ -52,9 +52,9 @@ static ArrayDimension* DimensionIntersection(const ArrayDimension& dim1, const A } /* dim1 / dim2 */ -static vector DimensionDifference(const ArrayDimension& dim1, const ArrayDimension& dim2) +static vector dimensionDifference(const ArrayDimension& dim1, const ArrayDimension& dim2) { - ArrayDimension* intersection = DimensionIntersection(dim1, dim2); + ArrayDimension* intersection = dimensionIntersection(dim1, dim2); if (!intersection) return { dim1 }; @@ -87,10 +87,10 @@ static vector DimensionDifference(const ArrayDimension& dim1, co } -static vector DimensionUnion(const ArrayDimension& dim1, const ArrayDimension& dim2) +static vector dimensionUnion(const ArrayDimension& dim1, const ArrayDimension& dim2) { vector res; - ArrayDimension* inter = DimensionIntersection(dim1, dim2); + ArrayDimension* inter = dimensionIntersection(dim1, dim2); if (!inter) return { dim1, dim2 }; @@ -98,14 +98,14 @@ static vector DimensionUnion(const ArrayDimension& dim1, const A delete(inter); vector diff1, diff2; - diff1 = DimensionDifference(dim1, dim2); - diff2 = DimensionDifference(dim2, dim1); + diff1 = dimensionDifference(dim1, dim2); + diff2 = dimensionDifference(dim2, dim1); res.insert(res.end(), diff1.begin(), diff1.end()); res.insert(res.end(), diff2.begin(), diff2.end()); return res; } -static vector ElementsIntersection(const vector& firstElement, const vector& secondElement) +static vector elementsIntersection(const vector& firstElement, const vector& secondElement) { if (firstElement.empty() || secondElement.empty()) return {}; @@ -113,13 +113,13 @@ static vector ElementsIntersection(const vector& size_t dimAmount = firstElement.size(); /* check if there is no intersecction */ for (size_t i = 0; i < dimAmount; i++) - if (FindParticularSolution(firstElement[i], secondElement[i]).empty()) + if (findParticularSolution(firstElement[i], secondElement[i]).empty()) return {}; vector result(dimAmount); for (size_t i = 0; i < dimAmount; i++) { - ArrayDimension* resPtr = DimensionIntersection(firstElement[i], secondElement[i]); + ArrayDimension* resPtr = dimensionIntersection(firstElement[i], secondElement[i]); if (resPtr) result[i] = *resPtr; else @@ -129,7 +129,7 @@ static vector ElementsIntersection(const vector& return result; } -static vector> ElementsDifference(const vector& firstElement, +static vector> elementsDifference(const vector& firstElement, const vector& secondElement) { if (firstElement.empty()) @@ -137,14 +137,14 @@ static vector> ElementsDifference(const vector intersection = ElementsIntersection(firstElement, secondElement); + vector intersection = elementsIntersection(firstElement, secondElement); vector> result; if (intersection.empty()) return { firstElement }; for (int i = 0; i < firstElement.size(); i++) { - auto dimDiff = DimensionDifference(firstElement[i], secondElement[i]); + auto dimDiff = dimensionDifference(firstElement[i], secondElement[i]); if (!dimDiff.empty()) { vector firstCopy = firstElement; @@ -158,14 +158,14 @@ static vector> ElementsDifference(const vector& firstElement, const vector& secondElement, +static void elementsUnion(const vector& firstElement, const vector& secondElement, vector>& lc, vector>& rc, vector& intersection) { /* lc(rc) is a set of ranges, which only exist in first(second) element*/ - intersection = ElementsIntersection(firstElement, secondElement); - lc = ElementsDifference(firstElement, intersection); - rc = ElementsDifference(secondElement, intersection); + intersection = elementsIntersection(firstElement, secondElement); + lc = elementsDifference(firstElement, intersection); + rc = elementsDifference(secondElement, intersection); } void AccessingSet::FindUncovered(const vector& element, vector>& result) const { @@ -175,8 +175,8 @@ void AccessingSet::FindUncovered(const vector& element, vector& element, vector> AccessingSet::GetElements() const { return allElements; } +const vector>& AccessingSet::GetElements() const { return allElements; } void AccessingSet::Insert(const vector& element) { @@ -283,7 +283,7 @@ bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs) return false; } -bool operator!=(const ArrayAccessingIndexes& lhs, const ArrayAccessingIndexes& rhs) +bool operator!=(const arrayAccessingIndexes& lhs, const arrayAccessingIndexes& rhs) { if (lhs.size() != rhs.size()) return true; diff --git a/src/PrivateAnalyzer/range_structures.h b/src/PrivateAnalyzer/range_structures.h index 6a609fc..4f58728 100644 --- a/src/PrivateAnalyzer/range_structures.h +++ b/src/PrivateAnalyzer/range_structures.h @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -22,7 +22,7 @@ public: AccessingSet(std::vector> input) : allElements(input) {}; AccessingSet() {}; AccessingSet(const AccessingSet& a) { allElements = a.GetElements(); }; - std::vector> GetElements() const; + const std::vector>& GetElements() const; void Insert(const std::vector& element); AccessingSet Union(const AccessingSet& source); AccessingSet Intersect(const AccessingSet& secondSet) const; @@ -33,8 +33,8 @@ public: friend bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs); }; -using ArrayAccessingIndexes = std::map; +using arrayAccessingIndexes = std::map; bool operator!=(const ArrayDimension& lhs, const ArrayDimension& rhs); bool operator!=(const AccessingSet& lhs, const AccessingSet& rhs); -bool operator!=(const ArrayAccessingIndexes& lhs, const ArrayAccessingIndexes& rhs); \ No newline at end of file +bool operator!=(const arrayAccessingIndexes& lhs, const arrayAccessingIndexes& rhs); \ No newline at end of file diff --git a/src/PrivateAnalyzer/region.cpp b/src/PrivateAnalyzer/region.cpp index 7e47308..8b226bf 100644 --- a/src/PrivateAnalyzer/region.cpp +++ b/src/PrivateAnalyzer/region.cpp @@ -1,8 +1,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -23,9 +23,9 @@ static bool isParentStmt(SgStatement* stmt, SgStatement* parent) } /*returns head block and loop*/ -pair> GetBasicBlocksForLoop(const LoopGraph* loop, const vector blocks) +pair> getBasicBlocksForLoop(const LoopGraph* loop, const vector blocks) { - unordered_set block_loop; + set block_loop; SAPFOR::BasicBlock* head_block = nullptr; auto loop_operator = loop->loop->GetOriginal(); for (const auto& block : blocks) @@ -51,16 +51,16 @@ pair> GetBasicBlocksForL return { head_block, block_loop }; } -static void BuildLoopIndex(map& loopForIndex, LoopGraph* loop) { +static void buildLoopIndex(map& loopForIndex, LoopGraph* loop) { string index = loop->loopSymbol(); - loopForIndex[index] = loop; + loopForIndex[loop->loop->GetOriginal()] = loop; for (const auto& childLoop : loop->children) - BuildLoopIndex(loopForIndex, childLoop); + buildLoopIndex(loopForIndex, childLoop); } -static string FindIndexName(int pos, SAPFOR::BasicBlock* block, map& loopForIndex) { - unordered_set args = { block->getInstructions()[pos]->getInstruction()->getArg1() }; +static string findIndexName(int pos, SAPFOR::BasicBlock* block, map& loopForIndex) { + set args = { block->getInstructions()[pos]->getInstruction()->getArg1() }; for (int i = pos - 1; i >= 0; i--) { @@ -93,10 +93,10 @@ static string FindIndexName(int pos, SAPFOR::BasicBlock* block, mapgetInstructions(); - map loopForIndex; - BuildLoopIndex(loopForIndex, loop); + map loopForIndex; + buildLoopIndex(loopForIndex, loop); for (int i = 0; i < instructions.size(); i++) { auto instruction = instructions[i]; @@ -136,7 +136,6 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces vector index_vars; vector refPos; string array_name = instruction->getInstruction()->getArg1()->getValue(); - int j = i - 1; while (j >= 0 && instructions[j]->getInstruction()->getOperation() == SAPFOR::CFG_OP::REF) { @@ -150,6 +149,8 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces vector accessPoint(n); auto* ref = isSgArrayRefExp(instruction->getInstruction()->getExpression()); + if (!ref) + continue; int fillCount = 0; vector> coeffsForDims; @@ -178,25 +179,16 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces string name, full_name = var->getValue(); int pos = full_name.find('%'); LoopGraph* currentLoop; - if (pos != -1) - { - name = full_name.substr(pos + 1); - if (loopForIndex.find(name) != loopForIndex.end()) - currentLoop = loopForIndex[name]; - else - return -1; - } - else - { - name = FindIndexName(currentVarPos, block, loopForIndex); - if (name == "") - return -1; - if (loopForIndex.find(name) != loopForIndex.end()) - currentLoop = loopForIndex[name]; - else - return -1; - } + auto serachInstr = instruction->getInstruction()->getOperator(); + while (serachInstr && serachInstr->variant() != FOR_NODE) + serachInstr = serachInstr->controlParent(); + + name = full_name.substr(pos + 1); + if (loopForIndex.find(serachInstr) != loopForIndex.end()) + currentLoop = loopForIndex[serachInstr]; + else + return -1; uint64_t start = coeffsForDims.back().second * currentLoop->startVal + coeffsForDims.back().first; uint64_t step = currentLoop->stepVal; @@ -204,7 +196,7 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces current_dim = { start, step, iters, ref }; } - if (current_dim.start != 0 && current_dim.step != 0 && current_dim.tripCount != 0) + if (current_dim.step != 0 && current_dim.tripCount != 0) { accessPoint[n - index_vars.size()] = current_dim; fillCount++; @@ -241,7 +233,7 @@ static int GetDefUseArray(SAPFOR::BasicBlock* block, LoopGraph* loop, ArrayAcces } -static void RemoveHeaderConnection(SAPFOR::BasicBlock* header, const unordered_set& blockSet, unordered_map& bbToRegion) +static void removeHeaderConnection(SAPFOR::BasicBlock* header, const set& blockSet, map& bbToRegion) { for (SAPFOR::BasicBlock* block : blockSet) { @@ -257,26 +249,56 @@ static void RemoveHeaderConnection(SAPFOR::BasicBlock* header, const unordered_s } } -static void DFS(Region* block, vector& result, unordered_set cycleBlocks) +static bool DFS(Region* block, vector& result, const set& cycleBlocks, map& color) { + auto it = color.find(block); + if (it != color.end()) + { + if (it->second == 0) + return false; + if (it->second == 1) + return true; + } + color[block] = 0; for (Region* nextBlock : block->getNextRegions()) { - if (cycleBlocks.find(nextBlock) != cycleBlocks.end()) - DFS(nextBlock, result, cycleBlocks); + if (cycleBlocks.find(nextBlock) == cycleBlocks.end()) + continue; + if (!DFS(nextBlock, result, cycleBlocks, color)) + return false; } + color[block] = 1; result.push_back(block); + return true; } -void TopologySort(std::vector& basikBlocks, Region* header) +bool hasCycle(Region* block, const std::set& cycleBlocks, std::set& visitedBlocks) { - vector result; - unordered_set cycleBlocks(basikBlocks.begin(), basikBlocks.end()); - DFS(header, result, cycleBlocks); - reverse(result.begin(), result.end()); - basikBlocks = result; + return false; + if (visitedBlocks.find(block) != visitedBlocks.end()) + return true; + visitedBlocks.insert(block); + for (Region* nextBlock : block->getNextRegions()) + { + if (cycleBlocks.find(nextBlock) != cycleBlocks.end() && hasCycle(nextBlock, cycleBlocks, visitedBlocks)) + return true; + } + return false; } -static void SetConnections(unordered_map& bbToRegion, const unordered_set& blockSet) +bool topologySort(std::vector& basikBlocks, Region* header) +{ + set cycleBlocks(basikBlocks.begin(), basikBlocks.end()); + vector result; + map color; + if (!DFS(header, result, cycleBlocks, color)) + return false; + reverse(result.begin(), result.end()); + basikBlocks = move(result); + return true; +} + +static void setConnections(map& bbToRegion, const set& blockSet) { for (SAPFOR::BasicBlock* block : blockSet) { @@ -290,11 +312,11 @@ static void SetConnections(unordered_map& bbToRegi } } -static Region* CreateSubRegion(LoopGraph* loop, const vector& Blocks, unordered_map& bbToRegion) +static Region* createSubRegion(LoopGraph* loop, const vector& Blocks, map& bbToRegion) { Region* region = new Region; - auto [header, blockSet] = GetBasicBlocksForLoop(loop, Blocks); - RemoveHeaderConnection(header, blockSet, bbToRegion); + auto [header, blockSet] = getBasicBlocksForLoop(loop, Blocks); + removeHeaderConnection(header, blockSet, bbToRegion); if (bbToRegion.find(header) != bbToRegion.end()) region->setHeader(bbToRegion.at(header)); else @@ -311,32 +333,34 @@ static Region* CreateSubRegion(LoopGraph* loop, const vectorisFor()) continue; - region->addSubRegions(CreateSubRegion(childLoop, Blocks, bbToRegion)); + region->addSubRegions(createSubRegion(childLoop, Blocks, bbToRegion)); } - TopologySort(region->getBasickBlocks(), region->getHeader()); + if (!topologySort(region->getBasickBlocks(), region->getHeader())) + throw std::runtime_error("Unnoticed cycle"); return region; } Region::Region(LoopGraph* loop, const vector& Blocks) { - auto [header, blockSet] = GetBasicBlocksForLoop(loop, Blocks); - unordered_map bbToRegion; + auto [header, blockSet] = getBasicBlocksForLoop(loop, Blocks); + map bbToRegion; for (auto poiner : blockSet) { bbToRegion[poiner] = new Region(*poiner); this->basickBlocks.push_back(bbToRegion[poiner]); - GetDefUseArray(poiner, loop, bbToRegion[poiner]->array_def, bbToRegion[poiner]->array_use, bbToRegion[poiner]); + getDefUseArray(poiner, loop, bbToRegion[poiner]->array_def, bbToRegion[poiner]->array_use, bbToRegion[poiner]); } this->header = bbToRegion[header]; - SetConnections(bbToRegion, blockSet); - RemoveHeaderConnection(header, blockSet, bbToRegion); + setConnections(bbToRegion, blockSet); + removeHeaderConnection(header, blockSet, bbToRegion); //create subRegions for (LoopGraph* childLoop : loop->children) { if (!childLoop->isFor()) continue; - subRegions.insert(CreateSubRegion(childLoop, Blocks, bbToRegion)); - } - TopologySort(basickBlocks, this->header); + subRegions.insert(createSubRegion(childLoop, Blocks, bbToRegion)); + } + if (!topologySort(basickBlocks, this->header)) + throw std::runtime_error("Unnoticed cycle"); } \ No newline at end of file diff --git a/src/PrivateAnalyzer/region.h b/src/PrivateAnalyzer/region.h index 3baa8a0..26d4a06 100644 --- a/src/PrivateAnalyzer/region.h +++ b/src/PrivateAnalyzer/region.h @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include "graph_loops.h" @@ -10,7 +10,7 @@ struct RegionInstruction { - ArrayAccessingIndexes def, use, in, out; + arrayAccessingIndexes def, use, in, out; }; class Region : public SAPFOR::BasicBlock { @@ -29,9 +29,9 @@ public: void addBasickBlocks(Region* region) { basickBlocks.push_back(region); } - const std::unordered_set& getPrevRegions() { return prevRegions; } + const std::set& getPrevRegions() { return prevRegions; } - std::unordered_set& getNextRegions() { return nextRegions; } + std::set& getNextRegions() { return nextRegions; } void removeNextRegion(Region* region) { @@ -61,22 +61,24 @@ public: nextRegions.insert(source); } - std::unordered_set getSubRegions() { return subRegions; } + std::set getSubRegions() { return subRegions; } void addSubRegions(Region* region) { subRegions.insert(region); } std::vector instructions; - ArrayAccessingIndexes array_def, array_use, array_out, array_in, array_priv; + arrayAccessingIndexes array_def, array_use, array_out, array_in, array_priv; private: std::vector basickBlocks; - std::unordered_set subRegions; + std::set subRegions; /*next Region which is BB for current BB Region*/ - std::unordered_set nextRegions; + std::set nextRegions; /*prev Regions which is BBs for current BB Region*/ - std::unordered_set prevRegions; + std::set prevRegions; Region* header; }; -void TopologySort(std::vector& basikBlocks, Region* header); \ No newline at end of file +bool hasCycle(Region* block, const std::set& cycleBlocks, std::set& visitedBlocks); + +bool topologySort(std::vector& basikBlocks, Region* header); \ No newline at end of file diff --git a/src/Sapfor.cpp b/src/Sapfor.cpp index a25ea29..96c129f 100644 --- a/src/Sapfor.cpp +++ b/src/Sapfor.cpp @@ -1,4 +1,4 @@ -#include "Utils/leak_detector.h" +#include "Utils/leak_detector.h" #pragma comment(linker, "/STACK:536870912") // 512 МБ @@ -23,6 +23,7 @@ #include "ParallelizationRegions/ParRegions_func.h" #include "ParallelizationRegions/resolve_par_reg_conflicts.h" #include "ParallelizationRegions/expand_extract_reg.h" +#include "ParallelizationRegions/merge_regions.h" #include "Distribution/Distribution.h" #include "Distribution/GraphCSR.h" @@ -741,7 +742,7 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne else if (curr_regime == LOOP_DATA_DEPENDENCIES) doDependenceAnalysisOnTheFullFile(file, 1, 1, 1); else if (curr_regime == REMOVE_DVM_DIRS || curr_regime == REMOVE_DVM_DIRS_TO_COMMENTS || curr_regime == REMOVE_SPF_DIRS) { - bool removeDvm = (curr_regime == REMOVE_DVM_DIRS || curr_regime == REMOVE_DVM_DIRS); + bool removeDvm = (curr_regime == REMOVE_DVM_DIRS); bool removeSpf = (curr_regime == REMOVE_SPF_DIRS); bool toComment = (curr_regime == REMOVE_DVM_DIRS_TO_COMMENTS); removeDvmSpfDirectives(file, removeDvm, removeSpf, toComment); @@ -1035,24 +1036,6 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne if (internalExit < 0) throw -1; - set applyFor = { LOOPS_SPLITTER, - LOOPS_COMBINER, - PRIVATE_REMOVING, - PRIVATE_ARRAYS_EXPANSION, - PRIVATE_ARRAYS_SHRINKING, - REMOVE_DEAD_CODE, - MOVE_OPERATORS }; - - if ((countOfTransform == 0 || internalExit > 0) && applyFor.find(curr_regime) != applyFor.end()) - { - SgStatement* mainUnit = findMainUnit(&project, SPF_messages); - checkNull(mainUnit, convertFileName(__FILE__).c_str(), __LINE__); - - getObjectForFileFromMap(mainUnit->fileName(), SPF_messages).push_back(Messages(ERROR, mainUnit->lineNumber(), R197, L"Transformation cannot be performed - nothing to change", 2023)); - __spf_print(1, "%d Transformation cannot be performed - nothing to change, count of transform %d, err %d\n", mainUnit->lineNumber(), countOfTransform, internalExit); - throw -11; - } - sendMessage_2lvl(2); // ********************************** /// /// SECOND AGGREGATION STEP /// @@ -1264,6 +1247,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne moveAllocatesInterproc(arrayLinksByFuncCalls); + propagateRegionInfo(declaredArrays, arrayLinksByFuncCalls, subs_parallelRegions); + removeDistrStateFromDeadFunctions(allFuncInfo, declaredArrays); propagateArrayFlags(arrayLinksByFuncCalls, declaredArrays, SPF_messages); } @@ -1681,30 +1666,11 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne findDeadFunctionsAndFillCalls(allFuncInfo_IR, SPF_messages, true); else if (curr_regime == GET_ALL_ARRAY_DECL) { - bool hasNonDefaultReg = false; - for (auto &elem : subs_parallelRegions) - if (elem->GetName() != "DEFAULT") - hasNonDefaultReg = true; - - if (hasNonDefaultReg) + if (ignoreArrayDistributeState) { - for (auto array : declaredArrays) - { - if (array.second.first->GetRegionsName().size() == 0) - array.second.first->SetDistributeFlag(DIST::NO_DISTR); - else if (array.second.first->GetRegionsName().size() == 1) - { - string regName = *array.second.first->GetRegionsName().begin(); - convertToLower(regName); - if (regName == "default") - array.second.first->SetDistributeFlag(DIST::NO_DISTR); - } - } - } - - if (ignoreArrayDistributeState) for (auto array : declaredArrays) array.second.first->SetDistributeFlag(DIST::NO_DISTR); + } } else if (curr_regime == GCOV_PARSER) { @@ -1920,11 +1886,14 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne } else if (curr_regime == TRANSFORM_ASSUMED_SIZE_PARAMETERS) transformAssumedSizeParameters(allFuncInfo); - else if (curr_regime == FIND_PRIVATE_ARRAYS_ANALYSIS) - FindPrivateArrays(loopGraph, fullIR, insertedPrivates); - + else if (curr_regime == FIND_PRIVATE_ARRAYS_ANALYSIS) + countOfTransform = findPrivateArrays(loopGraph, fullIR, insertedPrivates, SPF_messages, declaredArrays); + else if (curr_regime == MERGE_REGIONS) + mergeRegions(parallelRegions, allFuncInfo); else if (curr_regime == ARRAY_PROPAGATION) - ArrayConstantPropagation(project); + arrayConstantPropagation(project); + else if (curr_regime == ARRAY_PROPAGATION_RESTORE) + arrayConstantPropagationRrestore(); const float elapsed = duration_cast(high_resolution_clock::now() - timeForPass).count() / 1000.; const float elapsedGlobal = duration_cast(high_resolution_clock::now() - globalTime).count() / 1000.; @@ -1934,6 +1903,25 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne if (internalExit != 0) throw -1; + set applyFor = { LOOPS_SPLITTER, + LOOPS_COMBINER, + PRIVATE_REMOVING, + PRIVATE_ARRAYS_EXPANSION, + PRIVATE_ARRAYS_SHRINKING, + REMOVE_DEAD_CODE, + MOVE_OPERATORS, + FIND_PRIVATE_ARRAYS_ANALYSIS }; + + if ((countOfTransform == 0 || internalExit > 0) && applyFor.find(curr_regime) != applyFor.end()) + { + SgStatement* mainUnit = findMainUnit(&project, SPF_messages); + checkNull(mainUnit, convertFileName(__FILE__).c_str(), __LINE__); + + getObjectForFileFromMap(mainUnit->fileName(), SPF_messages).push_back(Messages(ERROR, mainUnit->lineNumber(), R197, L"Transformation cannot be performed - nothing to change", 2023)); + __spf_print(1, "%d Transformation cannot be performed - nothing to change, count of transform %d, err %d\n", mainUnit->lineNumber(), countOfTransform, internalExit); + throw - 11; + } + return true; } @@ -2379,6 +2367,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam case FIX_COMMON_BLOCKS: case TEST_PASS: case SET_IMPLICIT_NONE: + case MERGE_REGIONS: runAnalysis(*project, curr_regime, false); case SUBST_EXPR_RD_AND_UNPARSE: case SUBST_EXPR_AND_UNPARSE: diff --git a/src/Sapfor.h b/src/Sapfor.h index f5dadd1..a10a2d0 100644 --- a/src/Sapfor.h +++ b/src/Sapfor.h @@ -88,6 +88,8 @@ enum passes { REMOVE_DVM_INTERVALS, VERIFY_DVM_DIRS, + MERGE_REGIONS, + REMOVE_DIST_ARRAYS_FROM_IO, SUBST_EXPR, @@ -190,6 +192,7 @@ enum passes { TRANSFORM_ASSUMED_SIZE_PARAMETERS, ARRAY_PROPAGATION, + ARRAY_PROPAGATION_RESTORE, TEST_PASS, EMPTY_PASS @@ -273,6 +276,7 @@ static void setPassValues() passNames[VERIFY_DVM_DIRS] = "VERIFY_DVM_DIRS"; passNames[REMOVE_DVM_DIRS_TO_COMMENTS] = "REMOVE_DVM_DIRS_TO_COMMENTS"; passNames[REMOVE_SPF_DIRS] = "REMOVE_SPF_DIRS"; + passNames[MERGE_REGIONS] = "MERGE_REGIONS"; passNames[REMOVE_DIST_ARRAYS_FROM_IO] = "REMOVE_DIST_ARRAYS_FROM_IO"; passNames[SUBST_EXPR] = "SUBST_EXPR"; passNames[SUBST_EXPR_RD] = "SUBST_EXPR_RD"; @@ -381,7 +385,7 @@ static void setPassValues() passNames[TRANSFORM_ASSUMED_SIZE_PARAMETERS] = "TRANSFORM_ASSUMED_SIZE_PARAMETERS"; passNames[ARRAY_PROPAGATION] = "ARRAY_PROPAGATION"; - + passNames[ARRAY_PROPAGATION_RESTORE] = "ARRAY_PROPAGATION_RESTORE"; passNames[TEST_PASS] = "TEST_PASS"; } diff --git a/src/Transformations/ArrayConstantPropagation/propagation.cpp b/src/Transformations/ArrayConstantPropagation/propagation.cpp new file mode 100644 index 0000000..0b87937 --- /dev/null +++ b/src/Transformations/ArrayConstantPropagation/propagation.cpp @@ -0,0 +1,636 @@ +#include "propagation.h" + +#include "../Utils/SgUtils.h" + +#include +#include +#include +#include +#include + +using namespace std; + +static SgStatement* declPlace = NULL; +static set changed; +static map variablesToAdd; +static map> positionsToAdd; +static map arrayToName; +static map> statementsToRemove; +static map> expToChange; +static int variableNumber = 0; + +static bool checkConstIndexes(SgExpression* exp) +{ + if (!exp) + { + return false; + } + SgExpression* lhs = exp->lhs(); + SgExpression* rhs = exp->rhs(); + do + { + if (lhs && lhs->variant() != INT_VAL) + { + return false; + } + if (rhs) + { + lhs = rhs->lhs(); + rhs = rhs->rhs(); + } + } while (rhs); + return true; +} + +static SgExpression* createVar(SgType* type) +{ + string varName = "tmp_prop_var"; + string name = varName + std::to_string(variableNumber) + "__"; + variableNumber++; + + SgStatement* funcStart = declPlace->controlParent(); + SgSymbol* varSymbol = new SgSymbol(VARIABLE_NAME, name.c_str(), SgTypeInt(), funcStart); + + variablesToAdd[name] = varSymbol; + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + + return new SgExpression(VAR_REF, NULL, NULL, varSymbol, type->copyPtr()); +} + +static SgStatement* findLastDeclStatement(SgStatement* funcStart) +{ + if (!funcStart) + return NULL; + + SgStatement* endSt = funcStart->lastNodeOfStmt(); + SgStatement* cur = funcStart->lexNext(); + SgStatement* lastDecl = funcStart; + const set declVariants = { VAR_DECL, VAR_DECL_90, ALLOCATABLE_STMT, DIM_STAT, + EXTERN_STAT, COMM_STAT, HPF_TEMPLATE_STAT, DVM_VAR_DECL, STRUCT_DECL }; + + while (cur && cur != endSt) + { + if (cur->variant() == INTERFACE_STMT) + cur = cur->lastNodeOfStmt(); + + if (declVariants.find(cur->variant()) != declVariants.end()) + lastDecl = cur; + else if (isSgExecutableStatement(cur)) + break; + + cur = cur->lexNext(); + } + + return lastDecl; +} + +static void insertCommonAndDeclsForFunction(SgStatement* funcStart, const map& symbols) +{ + if (symbols.empty()) + return; + + if (!funcStart) + return; + + const string commonBlockName = "__propagation_common__"; + + SgStatement* funcEnd = funcStart->lastNodeOfStmt(); + SgStatement* commonStat = NULL; + SgExpression* commonList = NULL; + + for (SgStatement* cur = funcStart->lexNext(); + cur && cur != funcEnd; cur = cur->lexNext()) + { + if (cur->variant() != COMM_STAT) + continue; + + for (SgExpression* exp = cur->expr(0); exp; exp = exp->rhs()) + { + if (exp->variant() != COMM_LIST) + continue; + + const char* id = exp->symbol() ? exp->symbol()->identifier() : NULL; + string existingName = id ? string(id) : string("spf_unnamed"); + if (existingName == commonBlockName) + { + commonStat = cur; + commonList = exp; + break; + } + } + if (commonStat) + break; + } + + vector varRefs; + for (const auto& [name, sym] : symbols) + { + if (!sym || sym->variant() != VARIABLE_NAME || string(sym->identifier()) == commonBlockName) + continue; + SgSymbol* symToAdd = new SgSymbol(VARIABLE_NAME, name.c_str(), SgTypeInt(), funcStart); + varRefs.push_back(new SgVarRefExp(symToAdd)); + } + SgExpression* varList = makeExprList(varRefs, false); + + SgStatement* insertAfter = findLastDeclStatement(funcStart); + for (const auto& [name, sym] : symbols) + { + if (!sym) + continue; + SgStatement* declStmt = sym->makeVarDeclStmt(); + if (!declStmt) + continue; + + if (SgVarDeclStmt* vds = isSgVarDeclStmt(declStmt)) + vds->setVariant(VAR_DECL_90); + + declStmt->setFileName(funcStart->fileName()); + declStmt->setFileId(funcStart->getFileId()); + declStmt->setProject(funcStart->getProject()); + declStmt->setlineNumber(getNextNegativeLineNumber()); + + insertAfter->insertStmtAfter(*declStmt, *funcStart); + insertAfter = declStmt; + statementsToRemove[declStmt->fileName()].insert(declStmt); + } + + if (!commonList) + { + SgSymbol* commonSymbol = new SgSymbol(COMMON_NAME, commonBlockName.c_str()); + commonList = new SgExpression(COMM_LIST, varList, NULL, commonSymbol); + + commonStat = new SgStatement(COMM_STAT); + commonStat->setFileName(funcStart->fileName()); + commonStat->setFileId(funcStart->getFileId()); + commonStat->setProject(funcStart->getProject()); + commonStat->setlineNumber(getNextNegativeLineNumber()); + commonStat->setExpression(0, commonList); + + SgStatement* lastDecl = findLastDeclStatement(funcStart); + lastDecl->insertStmtAfter(*commonStat, *funcStart); + statementsToRemove[commonStat->fileName()].insert(commonStat); + } + else + commonList->setLhs(varList); + +} + +static void copyStatement(SgStatement* st) +{ + if (!st) + return; + + if (expToChange[st->fileName()].find(st) == expToChange[st->fileName()].end()) + { + SgStatement* boundCopy = st->copyPtr(); + + for (int i = 0; i < 3; i++) + { + SgExpression* expCopy = st->expr(i); + if (expCopy) + boundCopy->setExpression(i, expCopy->copyPtr()); + else + boundCopy->setExpression(i, NULL); + } + expToChange[st->fileName()][st] = boundCopy; + } +} + +static bool transformRightPart(SgStatement* st, SgExpression* exp, map& arrayToVariable) +{ + if (!exp) + return false; + bool isChanged = false; + vector subnodes = { exp->lhs(), exp->rhs() }; + + string expUnparsed; + SgExpression* toAdd = NULL; + if (isArrayRef(exp) && checkConstIndexes(exp->lhs())) + { + expUnparsed = exp->unparse(); + if (arrayToVariable.find(expUnparsed) == arrayToVariable.end() && exp && exp->symbol() && + exp->symbol()->type() && exp->symbol()->type()->baseType()) + { + arrayToVariable[expUnparsed] = createVar(exp->symbol()->type()->baseType()); + arrayToName[expUnparsed] = arrayToVariable[expUnparsed]->unparse(); + } + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + auto* sym = new SgSymbol(VARIABLE_NAME, arrayToName[expUnparsed].c_str(), SgTypeInt(), declPlace->controlParent()); + auto* newVarExp = new SgVarRefExp(sym); + copyStatement(st); + st->setExpression(1, newVarExp); + return true; + } + + for (int i = 0; i < 2; i++) + { + if (subnodes[i] && isArrayRef(subnodes[i]) && subnodes[i]->symbol() && subnodes[i]->symbol()->type() && + subnodes[i]->symbol()->type()->baseType() && checkConstIndexes(subnodes[i]->lhs())) + { + isChanged = true; + expUnparsed = subnodes[i]->unparse(); + if (arrayToVariable.find(expUnparsed) == arrayToVariable.end()) + { + arrayToVariable[expUnparsed] = createVar(subnodes[i]->symbol()->type()->baseType()); + arrayToName[expUnparsed] = arrayToVariable[expUnparsed]->unparse(); + } + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + SgSymbol* builder = arrayToVariable[expUnparsed]->symbol(); + auto* sym = new SgSymbol(VARIABLE_NAME, arrayToName[expUnparsed].c_str(), SgTypeInt(), declPlace->controlParent()); + toAdd = new SgVarRefExp(sym); + if (toAdd) + { + copyStatement(st); + if (i == 0) + exp->setLhs(toAdd); + else + exp->setRhs(toAdd); + } + } + else + isChanged = isChanged || transformRightPart(st, subnodes[i], arrayToVariable); + + } + return isChanged; +} + +static void transformLeftPart(SgStatement* st, SgExpression* exp, map& arrayToVariable) +{ + if (!st || !st->expr(1)) + return; + if (!exp || !exp->symbol() || !exp->symbol()->type() || !exp->symbol()->type()->baseType()) + return; + if (exp->symbol()->type()->variant() == T_STRING) + return; + if (changed.find(st) != changed.end()) + return; + + string expUnparsed = exp->unparse(); + if (arrayToVariable.find(expUnparsed) == arrayToVariable.end() && exp->symbol()->type()->baseType()) + { + arrayToVariable[expUnparsed] = createVar(exp->symbol()->type()->baseType()); + arrayToName[expUnparsed] = arrayToVariable[expUnparsed]->unparse(); + } + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + auto* sym = new SgSymbol(VARIABLE_NAME, arrayToName[expUnparsed].c_str(), SgTypeInt(), declPlace->controlParent()); + auto* newVarExp = new SgVarRefExp(sym); + SgStatement* newStatement = new SgStatement(ASSIGN_STAT, NULL, NULL, newVarExp, st->expr(1)->copyPtr(), NULL); + + newStatement->setFileId(st->getFileId()); + newStatement->setProject(st->getProject()); + + st->insertStmtBefore(*newStatement, *st->controlParent()); + + newStatement->setlineNumber(getNextNegativeLineNumber()); + newStatement->setLocalLineNumber(st->lineNumber()); + + changed.insert(st); + statementsToRemove[newStatement->fileName()].insert(newStatement); +} + +static void transformBorder(SgStatement* st, SgExpression* exp, map& arrayToVariable) +{ + if (!st || !exp) + return; + SgStatement* firstStatement = declPlace->lexPrev(); + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + transformRightPart(st, exp, arrayToVariable); + st = st->lexPrev(); + while (st &&st != firstStatement) + { + if (st->variant() == ASSIGN_STAT) + { + if (st->expr(1)) + { + transformRightPart(st, st->expr(1), arrayToVariable); + } + if (st->expr(0) && isArrayRef(st->expr(0)) && checkConstIndexes(st->expr(0)->lhs()) && arrayToVariable.find(st->expr(0)->unparse()) != arrayToVariable.end()) + transformLeftPart(st, st->expr(0), arrayToVariable); + } + st = st->lexPrev(); + } +} + +static void checkVariable(SgStatement* st, SgExpression* exp, map& arrayToVariable) +{ + SgStatement* firstStatement = declPlace->lexPrev(); + st = st->lexPrev(); + while (st != firstStatement) + { + if (st->variant() == ASSIGN_STAT && st->expr(0)->symbol() == exp->symbol()) + { + if (transformRightPart(st, st->expr(1), arrayToVariable)) + { + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + } + } + + if (st->variant() == ASSIGN_STAT && arrayToVariable.find(st->expr(0)->unparse()) != arrayToVariable.end()) + { + if (st->expr(1)) + { + if(transformRightPart(st, st->expr(1), arrayToVariable)) + { + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + } + } + if (st->expr(0) && isArrayRef(st->expr(0)) && checkConstIndexes(st->expr(0)->lhs()) && arrayToVariable.find(st->expr(0)->unparse()) != arrayToVariable.end()) + { + transformLeftPart(st, st->expr(0), arrayToVariable); + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + } + } + st = st->lexPrev(); + } +} + +static void findConstValues(SgProject& project, + const map>& borderVars, + const map& arrayToVariable, + map& hitCount, + map>>>& result) +{ + for (int i = 0; i < project.numberOfFiles(); i++) + { + SgFile* file = &(project.file(i)); + if (!file) + continue; + + SgFile::switchToFile(file->filename()); + const int funcNum = file->numberOfFunctions(); + for (int i = 0; i < funcNum; ++i) + { + SgStatement* st = file->functions(i); + SgStatement* lastNode = st->lastNodeOfStmt(); + if (!st) + continue; + for (; st != lastNode; st = st->lexNext()) + { + if (st && st->variant() == ASSIGN_STAT) + { + if (!st->expr(0) || !st->expr(1)) + continue; + SgExpression* lhs = st->expr(0); + SgExpression* rhs = st->expr(1); + auto varIt = arrayToVariable.find(lhs->unparse()); + string varName = (varIt != arrayToVariable.end()) ? varIt->second->unparse() : lhs->unparse(); + if (rhs->variant() == INT_VAL) + hitCount[string(lhs->unparse())]++; + for (const auto& [filename, names] : borderVars) + { + if(names.find(string(lhs->unparse())) != names.end() && rhs->variant() == INT_VAL) + result[filename][names.at(lhs->unparse())].push_back({ varName, rhs->unparse()}); + } + } + } + } + } +} + +static void insertDefinition(map>>>& definitions, map& hitCount) +{ + for (const auto& [filename, variables] : definitions) + { + if (SgFile::switchToFile(filename) == -1) + continue; + + for (const auto& [statement, values] : variables) + { + if (!statement) + continue; + + SgStatement* insertBefore = statement, *st = statement; + + while (st && !isSgExecutableStatement(st)) + { + st = st->lexNext(); + insertBefore = st; + } + + for (const auto& [varName, value] : values) + { + if (hitCount.find(varName) == hitCount.end() || hitCount[varName] > 1) + continue; + SgSymbol* sym = new SgSymbol(VARIABLE_NAME, varName.c_str(), SgTypeInt(), statement); + SgExpression* lhs = new SgVarRefExp(sym); + + SgExpression* rhs = new SgValueExp(stoi(value)); + + SgStatement* asg = new SgStatement(ASSIGN_STAT, NULL, NULL, lhs, rhs, NULL); + asg->setFileName(statement->fileName()); + asg->setFileId(statement->getFileId()); + asg->setProject(statement->getProject()); + asg->setlineNumber(getNextNegativeLineNumber()); + + if (insertBefore && insertBefore->controlParent()) + { + insertBefore->insertStmtBefore(*asg, *insertBefore->controlParent()); + statementsToRemove[asg->fileName()].insert(asg); + } + } + } + } +} + +static void applyLeftPartForUnchangedAssignments(SgProject& project, map& arrayToVariable) +{ + for (int fi = 0; fi < project.numberOfFiles(); ++fi) + { + SgFile* file = &(project.file(fi)); + if (!file) + continue; + + const string fileName = file->filename(); + if (SgFile::switchToFile(fileName) == -1) + continue; + + const int funcNum = file->numberOfFunctions(); + for (int fni = 0; fni < funcNum; ++fni) + { + SgStatement* funcStart = file->functions(fni); + if (!funcStart) + continue; + + declPlace = funcStart; + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + SgStatement* endSt = funcStart->lastNodeOfStmt(); + + for (SgStatement* st = funcStart; st && st != endSt; st = st->lexNext()) + { + if (st->variant() != ASSIGN_STAT) + continue; + if (!st->expr(0) || !st->expr(1)) + continue; + if (changed.find(st) != changed.end()) + continue; + + SgExpression* lhs = st->expr(0); + if (!isArrayRef(lhs)) + continue; + if (!lhs->symbol() || !lhs->symbol()->type()) + continue; + if (!lhs->symbol()->type()->baseType()) + continue; + if (!checkConstIndexes(lhs->lhs())) + continue; + + const string lhsUnparsed = lhs->unparse(); + if (arrayToVariable.find(lhsUnparsed) == arrayToVariable.end()) + continue; + + transformLeftPart(st, lhs, arrayToVariable); + } + } + } +} + +static bool containsArrayRefRecursive(SgExpression* exp) +{ + if (!exp) + return false; + + if (isArrayRef(exp) && checkConstIndexes(exp->lhs())) + return true; + + return containsArrayRefRecursive(exp->lhs()) || containsArrayRefRecursive(exp->rhs()); +} + +static void getBorderVars(SgExpression* exp, const string& filename, map>& borderVars) +{ + if (!exp) + return; + + if ((isArrayRef(exp) && checkConstIndexes(exp->lhs())) || exp->variant() == VAR_REF) + borderVars[filename][string(exp->unparse())] = declPlace; + + getBorderVars(exp->lhs(), filename, borderVars); + getBorderVars(exp->rhs(), filename, borderVars); +} + +static void processLoopBound(SgStatement* st, + SgExpression* bound, + const string& boundUnparsed, + bool isUpperBound, + map& arrayToVariable, + map>& borderVars) +{ + if (!bound || !st) + return; + + SgExpression* exp = isUpperBound ? bound->rhs() : bound->lhs(); + + getBorderVars(exp, st->fileName(), borderVars); + + if (containsArrayRefRecursive(exp)) + { + copyStatement(st); + + transformBorder(st, bound, arrayToVariable); + + positionsToAdd[string(declPlace->fileName())].insert(declPlace); + } + else if (bound->variant() == VAR_REF) + checkVariable(st, bound, arrayToVariable); +} + +void arrayConstantPropagation(SgProject& project) +{ + map arrayToVariable; + map> borderVars; + + for (int i = 0; i < project.numberOfFiles(); i++) + { + SgFile *file = &(project.file(i)); + + if (!file) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + if (SgFile::switchToFile(file->filename()) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + const int funcNum = file->numberOfFunctions(); + for (int i = 0; i < funcNum; ++i) + { + SgStatement* st = file->functions(i); + if (!st) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + declPlace = st; + SgStatement* lastNode = st->lastNodeOfStmt(); + + for (; st != lastNode; st = st->lexNext()) + { + if (st && st->variant() == FOR_NODE) + { + if (!st->expr(0)) + continue; + if (!st->expr(0)->lhs() || !st->expr(0)->rhs()) + continue; + SgExpression* lowerBound = st->expr(0)->lhs(); + SgExpression* upperBound = st->expr(0)->rhs(); + + + string lowerBoundUnparsed = lowerBound->unparse(); + string upperBoundUnparsed = upperBound->unparse(); + + processLoopBound(st, st->expr(0), upperBoundUnparsed, true, arrayToVariable, borderVars); + processLoopBound(st, st->expr(0), lowerBoundUnparsed, false, arrayToVariable, borderVars); + } + } + } + } + + applyLeftPartForUnchangedAssignments(project, arrayToVariable); + map> funcStarts; + for (const auto& [fileName, statements] : positionsToAdd) + { + int res = SgFile::switchToFile(fileName); + if (res == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (SgStatement* st : statements) + { + SgStatement* scope = isSgProgHedrStmt(st) ? st : st->controlParent(); + if (scope) + funcStarts[fileName].insert(scope); + } + } + + for (const auto& [fileName, statements] : funcStarts) + { + SgFile::switchToFile(fileName); + for (SgStatement* st : statements) + insertCommonAndDeclsForFunction(st, variablesToAdd); + } + + map>>> result; + map hitCount; + + findConstValues(project, borderVars, arrayToVariable, hitCount, result); + insertDefinition(result, hitCount); +} + +void arrayConstantPropagationRrestore() +{ + for (auto& [filename, statements] : expToChange) + { + if (SgFile::switchToFile(filename) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (auto& [statement, statementCopy] : statements) + { + if (statement && statementCopy) + for (int i = 0; i < 3; i++) + statement->setExpression(i, statementCopy->expr(i)); + } + } + + for (auto& [filename, statements] : statementsToRemove) + { + if (SgFile::switchToFile(filename) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (auto& st : statements) + st->deleteStmt(); + } +} diff --git a/src/Transformations/ArrayConstantPropagation/propagation.h b/src/Transformations/ArrayConstantPropagation/propagation.h new file mode 100644 index 0000000..547d96c --- /dev/null +++ b/src/Transformations/ArrayConstantPropagation/propagation.h @@ -0,0 +1,11 @@ +#pragma once +#include "../Utils/SgUtils.h" + +#include +#include + +using namespace std; + + +void arrayConstantPropagation(SgProject& project); +void arrayConstantPropagationRrestore(); diff --git a/src/Transformations/FunctionPurifying/function_purifying.cpp b/src/Transformations/FunctionPurifying/function_purifying.cpp index 7c65db2..0e8b03e 100644 --- a/src/Transformations/FunctionPurifying/function_purifying.cpp +++ b/src/Transformations/FunctionPurifying/function_purifying.cpp @@ -234,9 +234,8 @@ static bool hasDvmParallel(SgStatement *func) return false; } -void transformAssumedSizeParameters(const map>& allFuncInfo) -{ - map> assumedSizeArraysByFunc; +static map createDvmParallelInfo(const map>& allFuncInfo) { + map hasDvmParallelMap; for (auto& funcByFile : allFuncInfo) { @@ -249,7 +248,63 @@ void transformAssumedSizeParameters(const map>& allFun if (prog == NULL) continue; - if (!hasDvmParallel(prog)) + hasDvmParallelMap[func] = hasDvmParallel(prog); + } + } + + bool changed = true; + while (changed) + { + changed = false; + + for (auto& funcByFile : allFuncInfo) + { + for (auto& func : funcByFile.second) + { + if (!hasDvmParallelMap[func]) + { + bool hasParallel = false; + for (auto& callF : func->callsFromV) + { + if (hasDvmParallelMap[callF]) + { + hasParallel = true; + break; + } + } + + if (hasParallel) + { + changed = true; + hasDvmParallelMap[func] = true; + } + + } + } + } + } + + return hasDvmParallelMap; +} + + +void transformAssumedSizeParameters(const map>& allFuncInfo) +{ + map> assumedSizeArraysByFunc; + const map hasDvmParallelMap = createDvmParallelInfo(allFuncInfo); + + for (auto& funcByFile : allFuncInfo) + { + if (SgFile::switchToFile(funcByFile.first) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + for (auto& func : funcByFile.second) + { + SgProgHedrStmt* prog = isSgProgHedrStmt(func->funcPointer->GetOriginal()); + if (prog == NULL) + continue; + + if (!hasDvmParallelMap.at(func)) continue; vector parNames; @@ -259,7 +314,8 @@ void transformAssumedSizeParameters(const map>& allFun bool hasRefs = false; for (int z = 0; z < func->funcParams.countOfPars; ++z) { - if (func->funcParams.parametersT[z] == ARRAY_T) + if (func->funcParams.parametersT[z] == ARRAY_T || + func->funcParams.parametersT[z] == STRING_ARRAY_T) { auto s = prog->parameter(z); const string name = s->identifier(); diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index 0793913..686cbd3 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -5,125 +5,134 @@ #include #include #include +#include +#include #include "../../Utils/errors.h" #include "../../Utils/SgUtils.h" #include "../../GraphCall/graph_calls.h" -#include "../../GraphCall/graph_calls_func.h" #include "../../CFGraph/CFGraph.h" #include "../../CFGraph/IR.h" -#include "../../GraphLoop/graph_loops.h" #include "move_operators.h" using namespace std; -set loop_tags = {FOR_NODE}; +set loop_tags = {FOR_NODE, WHILE_NODE, DO_WHILE_NODE}; set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; set control_end_tags = {CONTROL_END}; -static vector findInstructionsFromStatement(SgStatement* st, const vector& blocks) +static bool isParentStmt(SgStatement* stmt, SgStatement* parent) { - vector result; - if (!st) - return result; + for (; stmt; stmt = stmt->controlParent()) + if (stmt == parent) + return true; + return false; +} - const int stmtId = st->id(); - for (auto* bb : blocks) +static bool isStatementInFile(SgStatement* st, const string& fileName) +{ + if (!st) + return false; + + const char* stmtFile = st->fileName(); + return stmtFile && fileName == stmtFile; +} + +static vector findLoopStatementsInFunction(SgStatement* funcStmt, const string& fileName) +{ + vector loops; + if (!funcStmt) + return loops; + + SgStatement* lastNode = funcStmt->lastNodeOfStmt(); + for (SgStatement* st = funcStmt; st && st != lastNode; st = st->lexNext()) + if (loop_tags.count(st->variant()) && isStatementInFile(st, fileName)) + loops.push_back(st); + + return loops; +} + +static SgStatement* firstSignificantOperatorInBlock(const SAPFOR::BasicBlock* bb, const string& fileName) +{ + if (!bb) + return nullptr; + + for (auto* ir : bb->getInstructions()) { - if (!bb) + if (!ir || !ir->getInstruction()) continue; - for (auto* ir : bb->getInstructions()) - { - if (!ir || !ir->getInstruction()) - continue; - - SgStatement* op = ir->getInstruction()->getOperator(); - if (op && op->id() == stmtId) - result.push_back(ir); - } + SgStatement* st = ir->getInstruction()->getOperator(); + if (isStatementInFile(st, fileName)) + return st; } - sort(result.begin(), result.end(), - [](const SAPFOR::IR_Block* a, const SAPFOR::IR_Block* b) { return a->getNumber() < b->getNumber(); }); - return result; + return nullptr; } -vector findFuncBlocksByFuncStatement(SgStatement *st, const map>& FullIR) { - vector result; - if (!st) - return result; +static SgStatement* lastSignificantOperatorInBlock(const SAPFOR::BasicBlock* bb, const string& fileName) +{ + if (!bb) + return nullptr; - Statement* forSt = (Statement*)st; - const string stmtFile = st->fileName(); - const int stmtLine = st->lineNumber(); - - for (auto& func: FullIR) { - if (!func.first || !func.first->funcPointer) + const auto& instructions = bb->getInstructions(); + for (auto it = instructions.rbegin(); it != instructions.rend(); ++it) + { + auto* ir = *it; + if (!ir || !ir->getInstruction()) continue; - const string funcFile = func.first->fileName; - const int funcLine = func.first->funcPointer->lineNumber(); - - // Important: select CFG blocks only for the same file and function header. - if (funcFile == stmtFile && funcLine == stmtLine) - { - result = func.second; - break; - } + SgStatement* st = ir->getInstruction()->getOperator(); + if (isStatementInFile(st, fileName)) + return st; } - return result; + + return nullptr; } -map> findAndAnalyzeLoops(SgStatement *st, const vector& blocks) { - map> result; - SgStatement *lastNode = st->lastNodeOfStmt(); - - while (st && st != lastNode) { - if (loop_tags.find(st -> variant()) != loop_tags.end()) { - SgForStmt *forSt = (SgForStmt*)st; - SgStatement *loopBody = forSt -> body(); - SgStatement *lastLoopNode = st->lastNodeOfStmt(); - set blocks_nums; - - while (loopBody && loopBody != lastLoopNode) { - vector irBlocks = findInstructionsFromStatement(loopBody, blocks); - if (!irBlocks.empty()) { - SAPFOR::IR_Block* IR = irBlocks.front(); - if (IR && IR->getBasicBlock()) { - if (blocks_nums.find(IR -> getBasicBlock() -> getNumber()) == blocks_nums.end()) { - result[forSt].push_back(IR -> getBasicBlock()); - blocks_nums.insert(IR -> getBasicBlock() -> getNumber()); - } - } - } - loopBody = loopBody -> lexNext(); - } - sort(result[forSt].begin(), result[forSt].end()); - } - st = st -> lexNext(); - } - return result; +static bool isBasicBlockInAnyLoop(const SAPFOR::BasicBlock* bb, const vector& loops, const string& fileName) +{ + SgStatement* first = firstSignificantOperatorInBlock(bb, fileName); + SgStatement* last = lastSignificantOperatorInBlock(bb, fileName); + if (!first || !last) + return false; + + for (auto* loop : loops) + if (loop && isParentStmt(first, loop) && isParentStmt(last, loop)) + return true; + + return false; } - -vector findBlocksInLoopsByFullIR( - SgStatement* funcStmt, +static vector findBlocksInLoopsByFullIR( + SgFile* file, const map>& FullIR) { vector result; - if (!funcStmt) + if (!file || !file->filename()) return result; - const vector funcBlocks = findFuncBlocksByFuncStatement(funcStmt, FullIR); - const auto loopsMapping = findAndAnalyzeLoops(funcStmt, funcBlocks); - + const string fileName = file->filename(); set uniq; - for (const auto& kv : loopsMapping) - for (auto* bb : kv.second) - if (bb) + + for (const auto& func : FullIR) + { + FuncInfo* funcInfo = func.first; + if (!funcInfo || !funcInfo->funcPointer) + continue; + + if (funcInfo->fileName != fileName) + continue; + + const vector loops = findLoopStatementsInFunction(funcInfo->funcPointer, fileName); + if (loops.empty()) + continue; + + for (auto* bb : func.second) + if (isBasicBlockInAnyLoop(bb, loops, fileName)) uniq.insert(bb); + } result.assign(uniq.begin(), uniq.end()); sort(result.begin(), result.end(), @@ -137,11 +146,10 @@ vector findBlocksInLoopsByFullIR( return result; } -static map> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb) +static map> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb) { - map> result; if (!bb) - return result; + return {}; auto isCompoundStmt = [](SgStatement* st) -> bool { @@ -151,121 +159,154 @@ static map> analyzeBasicBlockIntraDependencie return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v); }; - auto isTrackable = [](const SAPFOR::Argument* a) -> bool + auto normalizeSageString = [](const string& src) -> string { - if (!a) - return false; - const auto t = a->getType(); - return t == SAPFOR::CFG_ARG_TYPE::VAR || t == SAPFOR::CFG_ARG_TYPE::REG; - }; + string normalized; + bool prevSpace = false; - auto argKey = [&](const SAPFOR::Argument* a) -> string - { - if (!a) - return string(); - return to_string((int)a->getType()) + "#" + to_string((int)a->getMemType()) + "#" + a->getValue(); - }; - - auto memKeyFromInstr = [&](const SAPFOR::Instruction* instr) -> string - { - if (!instr) - return string(); - SgExpression* ex = instr->getExpression(); - if (!ex) - return string(); - - auto exprKey = [&](auto&& self, SgExpression* e) -> string + for (char ch : src) { - if (!e) - return string("_"); - - if (auto* ar = isSgArrayRefExp(e)) + const bool isSpace = std::isspace(static_cast(ch)); + if (isSpace) { - SgSymbol* sym = ar->symbol() ? OriginalSymbol(ar->symbol()) : nullptr; - string key = string("A(") + (sym ? sym->identifier() : "?"); - const int n = ar->numberOfSubscripts(); - for (int i = 0; i < n; ++i) - { - key += ","; - key += self(self, ar->subscript(i)); - } - key += ")"; - return key; + if (!normalized.empty()) + prevSpace = true; + continue; } - if (e->variant() == VAR_REF || e->variant() == CONST_REF) - { - SgSymbol* sym = e->symbol() ? OriginalSymbol(e->symbol()) : nullptr; - return string((e->variant() == VAR_REF) ? "V(" : "C(") + (sym ? sym->identifier() : "?") + ")"; - } + if (prevSpace && !normalized.empty()) + normalized += ' '; + normalized += ch; + prevSpace = false; + } - if (auto* v = isSgValueExp(e)) - { - if (e->variant() == INT_VAL) - return string("I(") + to_string(v->intValue()) + ")"; - if (e->variant() == BOOL_VAL) - return string("B(") + (v->boolValue() ? "1" : "0") + ")"; - if (e->variant() == CHAR_VAL) - return string("CH(") + string(1, v->charValue()) + ")"; - if (e->variant() == FLOAT_VAL) - return string("F(") + (v->floatValue() ? v->floatValue() : "") + ")"; - if (e->variant() == DOUBLE_VAL) - return string("D(") + (v->doubleValue() ? v->doubleValue() : "") + ")"; - if (e->variant() == STRING_VAL) - return string("S(") + (v->stringValue() ? v->stringValue() : "") + ")"; - } - - string key = string("N(") + to_string(e->variant()); - if (e->lhs()) - key += ",L=" + self(self, e->lhs()); - if (e->rhs()) - key += ",R=" + self(self, e->rhs()); - key += ")"; - return key; - }; - - return "MEMEX#" + exprKey(exprKey, ex); + return normalized; }; - auto isBarrier = [&](const SAPFOR::Instruction* instr) -> bool + auto sageExprToString = [&](SgExpression* expr) -> string { - if (!instr) - return true; - const auto op = instr->getOperation(); - switch (op) + if (!expr) + return string(); + + char* raw = expr->unparse(); + return normalizeSageString(raw ? string(raw) : string()); + }; + + auto arrayElementKey = [&](SgArrayRefExp* arrayRef) -> string + { + if (!arrayRef) + return string(); + + string key; + SgSymbol* sym = arrayRef->symbol() ? OriginalSymbol(arrayRef->symbol()) : nullptr; + if (sym && sym->identifier()) + key = sym->identifier(); + else + return sageExprToString(arrayRef); + + if (key.empty()) + return string(); + + key += "("; + for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i) { - case SAPFOR::CFG_OP::F_CALL: - case SAPFOR::CFG_OP::IO_PARAM: - case SAPFOR::CFG_OP::DVM_DIR: - case SAPFOR::CFG_OP::SPF_DIR: - case SAPFOR::CFG_OP::POINTER_ASS: - case SAPFOR::CFG_OP::EXIT: - return true; - default: - return false; + if (i) + key += ", "; + key += sageExprToString(arrayRef->subscript(i)); + } + key += ")"; + + return key; + }; + + function&)> collectUsedKeysFromExpression = + [&](SgExpression* expr, set& usedKeys) + { + if (!expr) + return; + + if (isSgValueExp(expr) || expr->variant() == CONST_REF) + return; + + if (auto* arrayRef = isSgArrayRefExp(expr)) + { + const string key = arrayElementKey(arrayRef); + if (!key.empty()) + usedKeys.insert(key); + + for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i) + collectUsedKeysFromExpression(arrayRef->subscript(i), usedKeys); + return; + } + + if (auto* call = isSgFunctionCallExp(expr)) + { + for (int i = 0; i < call->numberOfArgs(); ++i) + collectUsedKeysFromExpression(call->arg(i), usedKeys); + return; + } + + if (expr->variant() == VAR_REF) + { + SgSymbol* sym = expr->symbol() ? OriginalSymbol(expr->symbol()) : nullptr; + if (sym && sym->identifier()) + usedKeys.insert(sym->identifier()); + return; + } + + collectUsedKeysFromExpression(expr->lhs(), usedKeys); + collectUsedKeysFromExpression(expr->rhs(), usedKeys); + }; + + auto collectUsedKeysFromArraySubscripts = [&](SgArrayRefExp* arrayRef, set& usedKeys) + { + if (!arrayRef) + return; + + for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i) + collectUsedKeysFromExpression(arrayRef->subscript(i), usedKeys); + }; + + auto addOperatorDependencies = [&](SgStatement* stmt, + const set& usedKeys, + const map& varDeclarations, + map>& operatorsDependencies) + { + if (!stmt) + return; + + for (const string& key : usedKeys) + { + auto it = varDeclarations.find(key); + if (it != varDeclarations.end() && it->second && it->second != stmt) + operatorsDependencies[stmt].insert(it->second); } }; - auto isDef = [&](const SAPFOR::Instruction* instr) -> bool + auto declarationKeyFromLeftPart = [&](SgStatement* stmt) -> string { - if (!instr) - return false; - SAPFOR::Argument* r = instr->getResult(); - if (!isTrackable(r)) - return false; + if (!stmt || stmt->variant() != ASSIGN_STAT) + return string(); - const auto op = instr->getOperation(); - if (op == SAPFOR::CFG_OP::STORE || op == SAPFOR::CFG_OP::REC_REF_STORE) - return false; + SgExpression* lhs = stmt->expr(0); + if (!lhs) + return string(); - return true; + if (auto* arrayRef = isSgArrayRefExp(lhs)) + return arrayElementKey(arrayRef); + + if (lhs->variant() == VAR_REF) + { + SgSymbol* sym = lhs->symbol() ? OriginalSymbol(lhs->symbol()) : nullptr; + if (sym && sym->identifier()) + return sym->identifier(); + } + + return string(); }; - // Reaching definitions inside the BasicBlock in straight-line order: - // lastDef[var] = last operator in this block that defined it. - map> lastDef; - map> lastMemDef; - map> depsSets; + vector operatorsOrder; + set seenOperators; for (auto* ir : bb->getInstructions()) { @@ -273,111 +314,38 @@ static map> analyzeBasicBlockIntraDependencie continue; const SAPFOR::Instruction* instr = ir->getInstruction(); - SgStatement* opStmt = instr->getOperator(); - if (!opStmt) - continue; - if (isCompoundStmt(opStmt)) + SgStatement* stmt = instr->getOperator(); + if (!stmt || isCompoundStmt(stmt)) continue; - if (isBarrier(instr)) - { - for (auto it = lastDef.begin(); it != lastDef.end();) - { - const SAPFOR::Argument* a = it->second.second; - if (!a || a->isMemGlobal() || a->isParameter()) - it = lastDef.erase(it); - else - ++it; - } - for (auto it = lastMemDef.begin(); it != lastMemDef.end();) - { - const SAPFOR::Argument* a = it->second.second; - if (!a || a->isMemGlobal() || a->isParameter()) - it = lastMemDef.erase(it); - else - ++it; - } - } - - if (!result.count(opStmt)) - result[opStmt] = {}; - - auto addDep = [&](SAPFOR::Argument* use) - { - if (!isTrackable(use)) - return; - const string k = argKey(use); - auto it = lastDef.find(k); - if (it == lastDef.end()) - return; - if (it->second.first && it->second.first != opStmt) - depsSets[opStmt].insert(it->second.first); - }; - - auto addMemDep = [&](const string& key) - { - if (key.empty()) - return; - auto it = lastMemDef.find(key); - if (it == lastMemDef.end()) - return; - if (it->second.first && it->second.first != opStmt) - depsSets[opStmt].insert(it->second.first); - }; - - addDep(instr->getArg1()); - addDep(instr->getArg2()); - if (instr->getOperation() == SAPFOR::CFG_OP::RANGE) - addDep(instr->getResult()); - - if (instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) - addDep(instr->getResult()); - - if (instr->getOperation() == SAPFOR::CFG_OP::LOAD || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_LOAD) - { - const string memKey = memKeyFromInstr(instr); - addMemDep(memKey); - } - - if (isDef(instr)) - { - const string dk = argKey(instr->getResult()); - lastDef[dk] = { opStmt, instr->getResult() }; - } - - if (instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) - { - const string k = memKeyFromInstr(instr); - SAPFOR::Argument* base = instr->getArg1(); - if (!k.empty() && base) - lastMemDef[k] = { opStmt, base }; - addMemDep(k); - } + if (seenOperators.insert(stmt).second) + operatorsOrder.push_back(stmt); } - for (auto& kv : result) + map varDeclarations; + map> operatorsDependencies; + + for (SgStatement* stmt : operatorsOrder) { - SgStatement* op = kv.first; - auto it = depsSets.find(op); - if (it == depsSets.end()) - continue; + set usedKeys; + if (stmt) + { + collectUsedKeysFromExpression(stmt->expr(1), usedKeys); + collectUsedKeysFromArraySubscripts(isSgArrayRefExp(stmt->expr(0)), usedKeys); + } + addOperatorDependencies(stmt, usedKeys, varDeclarations, operatorsDependencies); - kv.second.assign(it->second.begin(), it->second.end()); - sort(kv.second.begin(), kv.second.end(), - [](SgStatement* a, SgStatement* b) - { - const int la = a ? a->lineNumber() : -1; - const int lb = b ? b->lineNumber() : -1; - if (la != lb) - return la < lb; - return a < b; - }); + const string declarationKey = declarationKeyFromLeftPart(stmt); + if (!declarationKey.empty()) + varDeclarations[declarationKey] = stmt; } - return result; + return operatorsDependencies; } -static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb, const char* expectedFile) +static bool reorderOperatorsInBasicBlockUsingDeps( + SAPFOR::BasicBlock* bb, + const map>& operatorsDependencies) { if (!bb) return false; @@ -407,18 +375,6 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb, const if (ops.size() < 2) return false; - // Check that analyzed BB is in the same file as the expected file - const char* bbFile = ops.front()->fileName(); - if (!bbFile) - bbFile = "(unknown)"; - if (expectedFile && strcmp(expectedFile, bbFile) != 0) - return false; - for (auto* st : ops) - { - if (!st || !st->fileName() || strcmp(st->fileName(), bbFile) != 0) - return false; - } - SgStatement* parent = ops.front()->controlParent(); if (!parent) return false; @@ -466,52 +422,72 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb, const return false; } - // Compute dependencies (inside BB) and build a new order by moving each statement - // as close as possible after its last dependency (if any). - const auto depsMap = analyzeBasicBlockIntraDependencies(bb); - vector order = ops; + map originalIndex; + for (int i = 0; i < (int)ops.size(); ++i) + originalIndex[ops[i]] = i; - auto indexIn = [](const vector& v, SgStatement* s) -> int - { - for (int i = 0; i < (int)v.size(); ++i) - if (v[i] == s) - return i; - return -1; - }; + map> moveAfter; + set moved; - for (SgStatement* s : ops) + for (SgStatement* st : ops) { - auto itDeps = depsMap.find(s); - if (itDeps == depsMap.end() || itDeps->second.empty()) - continue; - - int posS = indexIn(order, s); - if (posS < 0) + auto itDeps = operatorsDependencies.find(st); + if (itDeps == operatorsDependencies.end() || itDeps->second.empty()) continue; + SgStatement* lastDep = nullptr; int lastDepIdx = -1; for (SgStatement* dep : itDeps->second) { - const int j = indexIn(order, dep); - if (j >= 0) - lastDepIdx = max(lastDepIdx, j); + auto itIdx = originalIndex.find(dep); + if (itIdx != originalIndex.end() && itIdx->second > lastDepIdx) + { + lastDep = dep; + lastDepIdx = itIdx->second; + } } - if (lastDepIdx < 0) + if (!lastDep || lastDep == st) continue; - if (posS == lastDepIdx + 1) - continue; - - order.erase(order.begin() + posS); - - int lp = lastDepIdx; - if (posS < lastDepIdx) - lp = lastDepIdx - 1; - - const int insertAt = lp + 1; - order.insert(order.begin() + insertAt, s); + moveAfter[lastDep].push_back(st); + moved.insert(st); } + vector order; + order.reserve(ops.size()); + set emitted; + set active; + bool invalidOrder = false; + + function emitStatement = [&](SgStatement* st) + { + if (!st || invalidOrder || emitted.count(st)) + return; + if (active.count(st)) + { + invalidOrder = true; + return; + } + + active.insert(st); + emitted.insert(st); + order.push_back(st); + + auto itMovedAfter = moveAfter.find(st); + if (itMovedAfter != moveAfter.end()) + for (SgStatement* dependent : itMovedAfter->second) + emitStatement(dependent); + + active.erase(st); + }; + + for (SgStatement* st : ops) + if (!moved.count(st)) + emitStatement(st); + + if (invalidOrder || order.size() != ops.size()) + return false; + bool changed = false; for (size_t i = 0; i < ops.size(); ++i) if (ops[i] != order[i]) @@ -585,18 +561,14 @@ void moveOperators(SgFile* file, const mapfilename()) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - const int funcNum = file->numberOfFunctions(); - for (int i = 0; i < funcNum; ++i) - { - SgStatement* st = file->functions(i); + const auto loopBlocks = findBlocksInLoopsByFullIR(file, FullIR); - const auto loopBlocks = findBlocksInLoopsByFullIR(st, FullIR); - for (auto* bb : loopBlocks) - { - if (!bb) - continue; - if (reorderOperatorsInBasicBlockUsingDeps(bb, file->filename())) - countOfTransform += 1; - } + for (auto* bb : loopBlocks) + { + if (!bb) + continue; + const auto operatorsDependencies = analyzeBasicBlockIntraDependencies(bb); + if (reorderOperatorsInBasicBlockUsingDeps(bb, operatorsDependencies)) + countOfTransform += 1; } } diff --git a/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp b/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp index c40bdba..0989851 100644 --- a/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp +++ b/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp @@ -504,7 +504,7 @@ static void replaceArrayInFragment(SgSymbol* replace_symb, } } -static bool ioReginBorder(SgStatement* stat, SgStatement* last_io_bound) +static bool ioRegionBorder(SgStatement* stat, SgStatement* last_io_bound) { auto var = stat->variant(); @@ -535,14 +535,24 @@ static bool ioReginBorder(SgStatement* stat, SgStatement* last_io_bound) 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; } +FuncInfo* getCurrentFuncInfo(const vector& fileFuncInfo, int line) +{ + for (auto* func : fileFuncInfo) + { + if (func->linesNum.first <= line && line <= func->linesNum.second) + return func; + } + + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return NULL; +} + void replaceDistributedArraysInIO(vector& regions, const map>& allFuncInfo, map>& SPF_messages, @@ -562,6 +572,8 @@ void replaceDistributedArraysInIO(vector& regions, if (SgFile::switchToFile(current_file_name) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + FuncInfo *current_func_info = NULL; + auto func_info_it = allFuncInfo.find(current_file_name); if (func_info_it == allFuncInfo.end()) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); @@ -588,13 +600,12 @@ void replaceDistributedArraysInIO(vector& regions, { curr_stmt = lines.stats.first->GetOriginal(); end = lines.stats.second->GetOriginal()->lexNext(); + current_func_info = getCurrentFuncInfo(func_info_it->second, curr_stmt->lineNumber()); } map> need_replace; SgStatement* last_io_bound = NULL; - FuncInfo *current_func_info = NULL; - while (curr_stmt != end) { if (!curr_stmt) @@ -604,18 +615,7 @@ void replaceDistributedArraysInIO(vector& regions, if (var == PROC_HEDR || var == PROG_HEDR || var == FUNC_HEDR) { - current_func_info = NULL; - for (auto *func_info : func_info_it->second) - { - if (func_info->funcName == curr_stmt->symbol()->identifier()) - { - current_func_info = func_info; - break; - } - } - - if (!current_func_info) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + current_func_info = getCurrentFuncInfo(func_info_it->second, curr_stmt->lineNumber()); curr_stmt = curr_stmt->lexNext(); while (curr_stmt && !isSgExecutableStatement(curr_stmt)) @@ -628,7 +628,7 @@ void replaceDistributedArraysInIO(vector& regions, break; } - if (ioReginBorder(curr_stmt, last_io_bound)) + if (ioRegionBorder(curr_stmt, last_io_bound)) { for (const auto& by_array_to_copy : need_replace) { diff --git a/src/Utils/PassManager.h b/src/Utils/PassManager.h index 95b0e61..cca9f91 100644 --- a/src/Utils/PassManager.h +++ b/src/Utils/PassManager.h @@ -318,10 +318,11 @@ void InitPassesDependencies(map> &passDepsIn, set list({ VERIFY_INCLUDES, CORRECT_VAR_DECL }) <= Pass(SET_IMPLICIT_NONE); - list({ CALL_GRAPH2, CALL_GRAPH, BUILD_IR, LOOP_GRAPH, LOOP_ANALYZER_DATA_DIST_S2 }) <= Pass(FIND_PRIVATE_ARRAYS_ANALYSIS); - list({ FIND_PRIVATE_ARRAYS_ANALYSIS, CONVERT_LOOP_TO_ASSIGN, RESTORE_LOOP_FROM_ASSIGN, REVERT_SUBST_EXPR_RD }) <= Pass(FIND_PRIVATE_ARRAYS); + list({ ARRAY_PROPAGATION, CALL_GRAPH2, CALL_GRAPH, BUILD_IR, LOOP_GRAPH, LOOP_ANALYZER_DATA_DIST_S2 }) <= Pass(FIND_PRIVATE_ARRAYS_ANALYSIS); + list({ FIND_PRIVATE_ARRAYS_ANALYSIS, CONVERT_LOOP_TO_ASSIGN, RESTORE_LOOP_FROM_ASSIGN, REVERT_SUBST_EXPR_RD, ARRAY_PROPAGATION_RESTORE }) <= Pass(FIND_PRIVATE_ARRAYS); list({ BUILD_IR, CALL_GRAPH2, RESTORE_LOOP_FROM_ASSIGN, REVERT_SUBST_EXPR_RD }) <= Pass(MOVE_OPERATORS); + Pass(CREATE_TEMPLATE_LINKS) <= Pass(MERGE_REGIONS); passesIgnoreStateDone.insert({ CREATE_PARALLEL_DIRS, INSERT_PARALLEL_DIRS, INSERT_SHADOW_DIRS, EXTRACT_PARALLEL_DIRS, EXTRACT_SHADOW_DIRS, CREATE_REMOTES, UNPARSE_FILE, REMOVE_AND_CALC_SHADOW, diff --git a/src/Utils/SgUtils.cpp b/src/Utils/SgUtils.cpp index cb009ff..5360662 100644 --- a/src/Utils/SgUtils.cpp +++ b/src/Utils/SgUtils.cpp @@ -658,7 +658,7 @@ string removeIncludeStatsAndUnparse(SgFile *file, const char *fileName, const ch if (wasDeleted) { - if (str.size() || str.back() != '\n') + if (str.size() && str.back() != '\n') str += '\n'; st->setComments(str.c_str()); } diff --git a/src/Utils/errors.h b/src/Utils/errors.h index 274e779..7d8abe5 100644 --- a/src/Utils/errors.h +++ b/src/Utils/errors.h @@ -322,6 +322,7 @@ static const wchar_t *RR1_5 = L"RR1_5:"; static const wchar_t *RR1_6 = L"RR1_6:"; static const wchar_t *RR1_7 = L"RR1_7:"; static const wchar_t *RR1_8 = L"RR1_8:"; +static const wchar_t *RR1_9 = L"RR1_9:"; static const wchar_t *R2 = L"R2:"; static const wchar_t *R3 = L"R3:"; diff --git a/src/Utils/version.h b/src/Utils/version.h index 207a063..8d9adb2 100644 --- a/src/Utils/version.h +++ b/src/Utils/version.h @@ -1,3 +1,2 @@ #pragma once - -#define VERSION_SPF "2473" +#define VERSION_SPF "2487" diff --git a/src/VisualizerCalls/get_information.cpp b/src/VisualizerCalls/get_information.cpp index b7874f1..3d95737 100644 --- a/src/VisualizerCalls/get_information.cpp +++ b/src/VisualizerCalls/get_information.cpp @@ -1809,6 +1809,13 @@ int SPF_MoveOperators(void*& context, int winHandler, short* options, short* pro return simpleTransformPass(MOVE_OPERATORS, options, projName, folderName, output, outputMessage); } +int SPF_MergeRegions(void*& context, int winHandler, short* options, short* projName, short* folderName, string& output, string& outputMessage) +{ + MessageManager::clearCache(); + MessageManager::setWinHandler(winHandler); + return simpleTransformPass(MERGE_REGIONS, options, projName, folderName, output, outputMessage); +} + static inline void convertBackSlash(char *str, int strL) { for (int z = 0; z < strL; ++z) @@ -2519,6 +2526,8 @@ const wstring Sapfor_RunTransformation(const char* transformName_c, const char* retCode = SPF_InsertPrivateArrayDirectives(context, winHandler, optSh, projSh, fold, output, outputMessage); else if (whichRun == "SPF_MoveOperators") retCode = SPF_MoveOperators(context, winHandler, optSh, projSh, fold, output, outputMessage); + else if (whichRun == "SPF_MergeRegions") + retCode = SPF_MergeRegions(context, winHandler, optSh, projSh, fold, output, outputMessage); else if (whichRun == "SPF_CreateParallelVariant") { vector splited;