diff --git a/CMakeLists.txt b/CMakeLists.txt index 12e61a7..012efa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,11 +161,15 @@ 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) + src/ParallelizationRegions/resolve_par_reg_conflicts.h + src/ParallelizationRegions/uniq_name_creator.cpp + src/ParallelizationRegions/uniq_name_creator.h) set(ARRAY_PROP src/ArrayConstantPropagation/propagation.cpp src/ArrayConstantPropagation/propagation.h ) +set(MERGE_REGIONS src/ParallelizationRegions/merge_regions.cpp + src/ParallelizationRegions/merge_regions.h) set(TR_DEAD_CODE src/Transformations/DeadCodeRemoving/dead_code.cpp src/Transformations/DeadCodeRemoving/dead_code.h) @@ -426,6 +430,7 @@ set(SOURCE_EXE ${LOOP_ANALYZER} ${TRANSFORMS} ${PARALLEL_REG} + ${MERGE_REGIONS} ${PRIV} ${ARRAY_PROP} ${FDVM} @@ -479,6 +484,7 @@ source_group (GraphCall FILES ${GR_CALL}) source_group (GraphLoop FILES ${GR_LOOP}) source_group (LoopAnalyzer FILES ${LOOP_ANALYZER}) source_group (ParallelizationRegions FILES ${PARALLEL_REG}) +source_group (MergeRegions FILES ${MERGE_REGIONS}) source_group (PrivateAnalyzer FILES ${PRIV}) source_group (ArrayConstantPropagation FILES ${ARRAY_PROP}) source_group (FDVM_Compiler FILES ${FDVM}) diff --git a/src/ArrayConstantPropagation/propagation.cpp b/src/ArrayConstantPropagation/propagation.cpp index a9400fc..034c6b4 100644 --- a/src/ArrayConstantPropagation/propagation.cpp +++ b/src/ArrayConstantPropagation/propagation.cpp @@ -313,7 +313,7 @@ static void CheckVariable(SgStatement* st, SgExpression* exp, unordered_map arrayToVariable; int variableNumber = 0; diff --git a/src/ArrayConstantPropagation/propagation.h b/src/ArrayConstantPropagation/propagation.h index f33523c..65fe4ed 100644 --- a/src/ArrayConstantPropagation/propagation.h +++ b/src/ArrayConstantPropagation/propagation.h @@ -17,4 +17,4 @@ struct ExprRestoreEntry SgExpression* savedCopy; }; -void ArrayConstantPropagation(SgProject& project); \ No newline at end of file +void arrayConstantPropagation(SgProject& project); \ No newline at end of file diff --git a/src/ParallelizationRegions/merge_regions.cpp b/src/ParallelizationRegions/merge_regions.cpp new file mode 100644 index 0000000..4c68fb2 --- /dev/null +++ b/src/ParallelizationRegions/merge_regions.cpp @@ -0,0 +1,624 @@ +#include "leak_detector.h" + +#include +#include +#include "merge_regions.h" + +using std::map; +using std::set; +using std::pair; +using std::string; +using std::vector; + +//TODO: need to create new clause!! +static void parseMergeDirective(const char *comment, + vector> &parsed_mapping) +{ + while (comment) + { + auto *line_end = strchr(comment, '\n'); + + static const char prefix[] = "!!spf transform(merge_arrays("; + static const auto compare_chars = sizeof(prefix) - 1; + + if (strlen(comment) >= compare_chars) + { + std::string comment_cmp(comment, compare_chars); + convertToLower(comment_cmp); + + if (comment_cmp == prefix) + { + auto* pair_start = comment + compare_chars; + auto* comma = strchr(pair_start, ','); + if (comma) + { + auto* close_br = strchr(comma + 1, ')'); + if (close_br) + { + parsed_mapping.emplace_back( + string(pair_start, comma - pair_start), + string(comma + 1, close_br - comma - 1)); + } + } + } + } + + comment = line_end; + + if (comment) + comment++; + } +} + +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; +} + +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; +} + +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()) + { + if (curr_stmt->comments()) + { + vector> parsed_mapping; + parseMergeDirective(curr_stmt->comments(), parsed_mapping); + + for (const auto &p : parsed_mapping) + { + auto *found_array = getArrayFromDeclarated(curr_stmt, p.first); + if (found_array) + { + arrays_to_merge[p.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 041c2bc..b08dd5b 100644 --- a/src/PrivateAnalyzer/private_arrays_search.cpp +++ b/src/PrivateAnalyzer/private_arrays_search.cpp @@ -419,7 +419,7 @@ static void AddPrivateArraysToLoop(LoopGraph* loop, const ArrayAccessingIndexes& } } -void FindPrivateArrays(map>& loopGraph, map>& FullIR, set& insertedPrivates) +void findPrivateArrays(map>& loopGraph, map>& FullIR, set& insertedPrivates) { map result; for (const auto& [fileName, loops] : loopGraph) diff --git a/src/PrivateAnalyzer/private_arrays_search.h b/src/PrivateAnalyzer/private_arrays_search.h index ca5da48..8b8f02c 100644 --- a/src/PrivateAnalyzer/private_arrays_search.h +++ b/src/PrivateAnalyzer/private_arrays_search.h @@ -9,5 +9,4 @@ #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); +void findPrivateArrays(std::map>& loopGraph, std::map>& FullIR, std::set& insertedPrivates); diff --git a/src/PrivateAnalyzer/region.cpp b/src/PrivateAnalyzer/region.cpp index 94c1815..4b38739 100644 --- a/src/PrivateAnalyzer/region.cpp +++ b/src/PrivateAnalyzer/region.cpp @@ -23,7 +23,7 @@ static bool isParentStmt(SgStatement* stmt, SgStatement* parent) } /*returns head block and loop*/ -pair> GetBasicBlocksForLoop(const LoopGraph* loop, const vector blocks) +static pair> GetBasicBlocksForLoop(const LoopGraph* loop, const vector blocks) { unordered_set block_loop; SAPFOR::BasicBlock* head_block = nullptr; diff --git a/src/Sapfor.cpp b/src/Sapfor.cpp index a78cb70..5a89c73 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" @@ -1904,10 +1905,11 @@ 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); - + findPrivateArrays(loopGraph, fullIR, insertedPrivates); + else if (curr_regime == MERGE_REGIONS) + mergeRegions(parallelRegions, allFuncInfo); else if (curr_regime == ARRAY_PROPAGATION) - ArrayConstantPropagation(project); + arrayConstantPropagation(project); const float elapsed = duration_cast(high_resolution_clock::now() - timeForPass).count() / 1000.; const float elapsedGlobal = duration_cast(high_resolution_clock::now() - globalTime).count() / 1000.; @@ -2362,6 +2364,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..bae94fb 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, @@ -273,6 +275,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"; diff --git a/src/Utils/PassManager.h b/src/Utils/PassManager.h index cd69c2f..68a6f6b 100644 --- a/src/Utils/PassManager.h +++ b/src/Utils/PassManager.h @@ -322,6 +322,7 @@ void InitPassesDependencies(map> &passDepsIn, set list({ FIND_PRIVATE_ARRAYS_ANALYSIS, CONVERT_LOOP_TO_ASSIGN, RESTORE_LOOP_FROM_ASSIGN, REVERT_SUBST_EXPR_RD }) <= 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/version.h b/src/Utils/version.h index c4c9c11..11f57e0 100644 --- a/src/Utils/version.h +++ b/src/Utils/version.h @@ -1,3 +1,3 @@ #pragma once -#define VERSION_SPF "2479" +#define VERSION_SPF "2480"