diff --git a/sapfor/experts/Sapfor_2017/CMakeLists.txt b/sapfor/experts/Sapfor_2017/CMakeLists.txt index b06ff45..438cb1a 100644 --- a/sapfor/experts/Sapfor_2017/CMakeLists.txt +++ b/sapfor/experts/Sapfor_2017/CMakeLists.txt @@ -193,6 +193,8 @@ set(TR_CONV _src/Transformations/convert_to_c.cpp _src/Transformations/convert_to_c.h) set(TR_IMPLICIT_NONE _src/Transformations/set_implicit_none.cpp _src/Transformations/set_implicit_none.h) +set(TR_REPLACE_ARRAYS_IN_IO _src/Transformations/replace_dist_arrays_in_io.cpp + _src/Transformations/replace_dist_arrays_in_io.h) set(TRANSFORMS ${TR_DEAD_CODE} @@ -211,7 +213,8 @@ set(TRANSFORMS ${TR_PRIV_DEL} ${TR_CONV} ${TR_PRIV_DEL} - ${TR_IMPLICIT_NONE}) + ${TR_IMPLICIT_NONE} + ${TR_REPLACE_ARRAYS_IN_IO}) set(CFG _src/CFGraph/IR.cpp _src/CFGraph/IR.h @@ -316,7 +319,7 @@ set(LOOP_ANALYZER _src/LoopAnalyzer/allocations_prepoc.cpp set(RENAME_SYMBOLS _src/RenameSymbols/rename_symbols.cpp _src/RenameSymbols/rename_symbols.h) - + set(MAIN _src/Sapfor.cpp _src/Sapfor.h @@ -444,6 +447,7 @@ source_group (Transformations\\RenameSymbols FILES ${RENAME_SYMBOLS}) source_group (Transformations\\GlobalVariables FILES ${TR_GV}) 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 (CreateIntervals FILES ${CREATE_INTER_T}) diff --git a/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp b/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp index 4321705..277b46c 100644 --- a/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp +++ b/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.cpp @@ -958,13 +958,13 @@ static bool replaceCommonArray(const string &fileName, return false; } -static pair copyArray(const pair &place, - const DIST::Array *array, - const vector& lines, - const string &suffix, - string& filename, - map>>& newDeclsToInclude, - map>>& copied) +pair copyArray(const pair &place, + const DIST::Array *array, + const vector& lines, + const string &suffix, + string& filename, + map>>& newDeclsToInclude, + map>>& copied) { string fileName = place.first; int switchRes = SgFile::switchToFile(fileName); diff --git a/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.h b/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.h index b12c399..4e5e3c4 100644 --- a/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.h +++ b/sapfor/experts/Sapfor_2017/_src/ParallelizationRegions/resolve_par_reg_conflicts.h @@ -13,4 +13,12 @@ int printCheckRegions(const char *fileName, const std::vector & bool checkRegionsResolving(const std::vector ®ions, const std::map> &allFuncInfo, const std::map &commonBlocks, std::map> &SPF_messages, bool sharedMemoryParallelization); int resolveParRegions(std::vector& regions, const std::map>& allFuncInfo, std::map>& SPF_messages, bool sharedMemoryParallelization, std::map>>& copyDecls); -void insertRealignsBeforeFragments(ParallelRegion* reg, SgFile* file, const std::set& distrArrays, const std::map>& arrayLinksByFuncCalls); \ No newline at end of file +void insertRealignsBeforeFragments(ParallelRegion* reg, SgFile* file, const std::set& distrArrays, const std::map>& arrayLinksByFuncCalls); + +std::pair copyArray(const std::pair& place, + const DIST::Array* array, + const std::vector& lines, + const std::string& suffix, + std::string& filename, + std::map>>& newDeclsToInclude, + std::map>>& copied); \ No newline at end of file diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp index 98bea28..b9e4bbb 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.cpp @@ -24,6 +24,8 @@ #include "ParallelizationRegions/resolve_par_reg_conflicts.h" #include "ParallelizationRegions/expand_extract_reg.h" +#include "Transformations/replace_dist_arrays_in_io.h" + #include "Distribution/Distribution.h" #include "Distribution/GraphCSR.h" #include "Distribution/Arrays.h" @@ -1567,6 +1569,10 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne if (error) internalExit = 1; } + else if (curr_regime == REMOVE_DIST_ARRAYS_FROM_IO) + { + replaceDistributedArraysInIO(parallelRegions, allFuncInfo, SPF_messages, newCopyDeclToIncl); + } else if (curr_regime == LOOP_GRAPH) { if (keepFiles) @@ -2333,6 +2339,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam findFunctionsToInclude(true); break; // all these cases run UNPARSE_FILE after + case REMOVE_DIST_ARRAYS_FROM_IO: case RENAME_SYMBOLS: case RESOLVE_PAR_REGIONS: case CREATE_PARALLEL_REGIONS: diff --git a/sapfor/experts/Sapfor_2017/_src/Sapfor.h b/sapfor/experts/Sapfor_2017/_src/Sapfor.h index 0bfc452..d37b0fb 100644 --- a/sapfor/experts/Sapfor_2017/_src/Sapfor.h +++ b/sapfor/experts/Sapfor_2017/_src/Sapfor.h @@ -87,6 +87,8 @@ enum passes { REMOVE_DVM_INTERVALS, VERIFY_DVM_DIRS, + REMOVE_DIST_ARRAYS_FROM_IO, + SUBST_EXPR, SUBST_EXPR_RD, REVERT_SUBST_EXPR, @@ -260,6 +262,7 @@ static void setPassValues() passNames[INSERT_INCLUDES] = "INSERT_INCLUDES"; passNames[REMOVE_DVM_DIRS] = "REMOVE_DVM_DIRS"; passNames[VERIFY_DVM_DIRS] = "VERIFY_DVM_DIRS"; + passNames[REMOVE_DIST_ARRAYS_FROM_IO] = "REMOVE_DIST_ARRAYS_FROM_IO"; passNames[SUBST_EXPR] = "SUBST_EXPR"; passNames[SUBST_EXPR_RD] = "SUBST_EXPR_RD"; passNames[CALL_GRAPH2] = "CALL_GRAPH2"; diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/replace_dist_arrays_in_io.cpp b/sapfor/experts/Sapfor_2017/_src/Transformations/replace_dist_arrays_in_io.cpp new file mode 100644 index 0000000..bc4b9b8 --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/replace_dist_arrays_in_io.cpp @@ -0,0 +1,394 @@ +#include "replace_dist_arrays_in_io.h" + +#include "../ParallelizationRegions/resolve_par_reg_conflicts.h" + +#include +#include +#include + +using std::map; +using std::set; +using std::string; +using std::to_string; +using std::make_pair; + +#define DEBUG_TRACE 0 + +static void findArrays(SgExpression* exp, set& arrays) +{ + if (exp) + { + if (isSgArrayRefExp(exp)) + arrays.insert(exp->symbol()); + + findArrays(exp->lhs(), arrays); + findArrays(exp->rhs(), arrays); + } +} + +static void populateDistributedIoArrays(map>& arrays, SgStatement* stat) +{ + auto var = stat->variant(); + + if (var != READ_STAT && var != PRINT_STAT && var != WRITE_STAT) + return; + + // check if such IO allowed in dvm: + // list should consist only of single array and format string should be * + + bool need_replace = false; + + SgExpression* ioList = stat->expr(0); + + if (!ioList) + return; + + if (ioList->variant() != EXPR_LIST) + return; + + if (ioList->rhs() == NULL) + { + SgExpression* arg = ioList->lhs(); + if (!arg) + return; + + if (arg->variant() != ARRAY_REF) + return; + + if (arg->lhs()) + need_replace = true; + } + else + { + need_replace = true; + } + + if (!need_replace) + { + switch (var) + { + case PRINT_STAT: + { + SgExpression* fmt = stat->expr(1); + if (!fmt || fmt->variant() != SPEC_PAIR || fmt->lhs()->variant() != KEYWORD_VAL) + { + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return; + } + + if (fmt->rhs()->variant() != KEYWORD_VAL || fmt->rhs()->sunparse() != "*") + need_replace = true; + + + break; + } + case READ_STAT: + case WRITE_STAT: + { + + SgExpression* spec = stat->expr(1); + __spf_print(DEBUG_TRACE, "[%d: %s (%d)]\n", 2000, spec->rhs()->unparse(), spec->rhs()->variant()); + if (!spec || spec->variant() != EXPR_LIST || + spec->lhs()->variant() != SPEC_PAIR || + !spec->rhs() || !spec->rhs()->lhs() || spec->rhs()->lhs()->variant() != SPEC_PAIR) + { + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return; + } + + SgExpression* unit_val = spec->lhs()->rhs(), * fmt_val = spec->rhs()->lhs()->rhs(); + + if (unit_val->variant() != KEYWORD_VAL || unit_val->sunparse() != "*" || + fmt_val->variant() != KEYWORD_VAL || fmt_val->sunparse() != "*") + need_replace = true; + + break; + } + } + } + + if (!need_replace) + return; + + set found_arrays; + + for (int i = 0; i < 3; i++) + findArrays(stat->expr(i), found_arrays); + + for (auto* by_symb : found_arrays) + { + string array_name = string(by_symb->identifier()); + DIST::Array* array_p = getArrayFromDeclarated(declaratedInStmt(by_symb), array_name); + if (arrays[array_p].insert(stat).second) + __spf_print(DEBUG_TRACE, "[%d]: add array %s\n", stat->lineNumber(), array_p->GetName().c_str()); + } + + __spf_print(DEBUG_TRACE, "[replace]\n"); +} + +static void replaceArrayRec(SgSymbol* arr, SgSymbol* replace_by, SgExpression* exp) +{ + if (!exp) + return; + + if (exp->symbol() && strcmp(exp->symbol()->identifier(), arr->identifier()) == 0) + exp->setSymbol(replace_by); + + replaceArrayRec(arr, replace_by, exp->lhs()); + replaceArrayRec(arr, replace_by, exp->rhs()); +} + +static void copyArrayBetweenStatements(SgSymbol* replace_symb, SgSymbol* replace_by, SgStatement* start, SgStatement* last) +{ + while (start->lexNext() && !isSgExecutableStatement(start->lexNext())) + start = start->lexNext(); + + auto* stop = last->lexNext(); + for (auto* st = start; st != stop; st = st->lexNext()) + for (int i = 0; i < 3; i++) + replaceArrayRec(replace_symb, replace_by, st->expr(i)); + + // A_copy = A + SgAssignStmt* assign = new SgAssignStmt(*new SgArrayRefExp(*replace_by), *new SgArrayRefExp(*replace_symb)); + assign->setlineNumber(getNextNegativeLineNumber()); // before region + auto* parent = start->controlParent(); + if (parent && parent->lastNodeOfStmt() == start) + parent = parent->controlParent(); + + start->insertStmtAfter(*assign, *parent); + + // A = A_reg + assign = new SgAssignStmt(*new SgArrayRefExp(*replace_symb), *new SgArrayRefExp(*replace_by)); + //TODO: bug with insertion + //assign->setlineNumber(getNextNegativeLineNumber()); // after region + last->insertStmtBefore(*assign, *(last->controlParent())); +} + +static void replaceArrayInFragment(DIST::Array* arr, const set usages, SgSymbol* replace_by, SgStatement* start, SgStatement* last, const string& filename) +{ + while (start->lexNext() && !isSgExecutableStatement(start->lexNext())) + start = start->lexNext(); + + auto* replace_symb = arr->GetDeclSymbol(); + + set not_opened, not_closed, copied; + + for (auto* it = start; it; it = it->controlParent()) + not_opened.insert(it); + + for (auto* it = last; it; it = it->controlParent()) + not_closed.insert(it); + + for (auto* io_stmt : usages) + { + bool already_copied = false; + SgStatement* copy_scope = NULL; + + for (auto* par = io_stmt; par; par = par->controlParent()) + { + if (copied.find(par) != copied.end()) + { + already_copied = true; + break; + } + else if (not_opened.find(par) != not_opened.end() || not_closed.find(par) != not_closed.end()) + { + copy_scope = par; + break; + } + } + + + if (already_copied) + continue; + + auto* scope_start = copy_scope, * scope_end = copy_scope->lastNodeOfStmt(); + __spf_print(DEBUG_TRACE, "[scope to copy] %d\n", copy_scope->lineNumber()); + + if (not_opened.find(copy_scope) != not_opened.end()) + { + auto* from = start->lastNodeOfStmt() ? start->lastNodeOfStmt() : start; + for (auto* st = from; st; st = st->controlParent()) + { + __spf_print(DEBUG_TRACE, "[find start of parent %d] %d\n", copy_scope->lineNumber(), st->lineNumber()); + + if (st->controlParent() == copy_scope) + { + scope_start = st->lastNodeOfStmt() ? st->lastNodeOfStmt() : st; + break; + } + } + } + + if (not_closed.find(copy_scope) != not_closed.end()) + { + for (auto* st = last; st; st = st->controlParent()) + { + __spf_print(DEBUG_TRACE, "[find end of parent %d] %d\n", copy_scope->lineNumber(), st->lineNumber()); + + if (st->controlParent() == copy_scope) + { + scope_end = st; + break; + } + } + } + + copyArrayBetweenStatements(replace_symb, replace_by, scope_start, scope_end); + __spf_print(DEBUG_TRACE, "[copy %s] [%d, %d]\n", arr->GetName().c_str(), scope_start->lineNumber(), scope_end->lineNumber()); + copied.insert(copy_scope); + } +} + +static bool ioReginBound(SgStatement* stat, SgStatement* last_io_bound) +{ + auto var = stat->variant(); + + if (var == PROC_STAT || var == FUNC_STAT || var == PROG_HEDR || var == FUNC_HEDR || var == PROC_HEDR || var == FUNC_STAT || var == FOR_NODE || var == LOOP_NODE) + return true; + + if (last_io_bound && last_io_bound->lastNodeOfStmt() && last_io_bound->lastNodeOfStmt() == stat) + return true; + + int parent_var; + + if (var == CONTROL_END && + ((parent_var = stat->controlParent()->variant()) == PROG_HEDR || + parent_var == PROC_HEDR || parent_var == FUNC_HEDR)) + { + return true; + } + + return false; +} + +void replaceDistributedArraysInIO(std::vector& regions, + const std::map>& allFuncInfo, + std::map>& SPF_messages, + map>>& newDeclsToInclude) +{ + map created_copies; + map>> copied; + + for (auto& region : regions) + { + __spf_print(DEBUG_TRACE, "[%s]: enter region\n", region->GetName().c_str()); + + for (auto& linesByFile : region->GetAllLinesToModify()) + { + const auto& filename = linesByFile.first; + + if (SgFile::switchToFile(filename) < 0) { + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return; + } + + for (auto& lines : linesByFile.second) { + __spf_print(DEBUG_TRACE, "[fragment] %s: %d:%d %d\n", filename.c_str(), lines.lines.first, + lines.lines.second, lines.isImplicit()); + + SgStatement* curr_stmt, * end; + + if (lines.isImplicit()) + { + + curr_stmt = current_file->SgStatementAtLine(lines.lines.first); + end = current_file->SgStatementAtLine(lines.lines.second); + + if (end) + end = end->lexNext(); + } + else + { + curr_stmt = lines.stats.first->GetOriginal(); + end = lines.stats.second->GetOriginal()->lexNext(); + } + + map> need_replace; + SgStatement* last_io_bound = NULL; + + + while (curr_stmt != end) + { + if (!curr_stmt) + break; + + auto var = curr_stmt->variant(); + + + if (var == PROC_HEDR || var == PROG_HEDR || var == FUNC_HEDR) + { + curr_stmt = curr_stmt->lexNext(); + while (curr_stmt && !isSgExecutableStatement(curr_stmt)) + { + last_io_bound = curr_stmt; + curr_stmt = curr_stmt->lexNext(); + } + + if (!curr_stmt) + break; + } + + if (ioReginBound(curr_stmt, last_io_bound)) + { + if (last_io_bound) + { + __spf_print(DEBUG_TRACE, "[io region] [%d, %d]\n", last_io_bound->lineNumber(), curr_stmt->lineNumber()); + + for (const auto& p : need_replace) + { + auto it = created_copies.find(p.first); + if (it != created_copies.end()) + replaceArrayInFragment(p.first, p.second, it->second, last_io_bound, curr_stmt, filename); + else + { + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return; + } + } + } + + need_replace.clear(); + last_io_bound = curr_stmt; + } + + __spf_print(DEBUG_TRACE, "[line] %d (%d)\n", curr_stmt->lineNumber(), curr_stmt->variant()); + + for (int i = 0; i < 3; i++) + { + if (curr_stmt->expr(i)) + { + __spf_print(DEBUG_TRACE, "[%d: %s (%d)]\n", i, curr_stmt->expr(i)->unparse(), curr_stmt->expr(i)->variant()); + } + } + + populateDistributedIoArrays(need_replace, curr_stmt); + + for (const auto& by_array_to_copy : need_replace) + { + auto* array_to_copy = by_array_to_copy.first; + auto it = created_copies.find(array_to_copy); + + if (it == created_copies.end()) + { + bool fromModule = (array_to_copy->GetLocation().first == DIST::l_MODULE); + const string locationName = array_to_copy->GetLocation().second; + + auto place = *array_to_copy->GetDeclInfo().begin(); + string fileName = place.first; + string suffix = "_io_l"; + + if (fromModule) + suffix = "_io_m"; + + auto origCopy = copyArray(place, array_to_copy, linesByFile.second, suffix + to_string(region->GetId()), fileName, newDeclsToInclude, copied); + created_copies.insert({ array_to_copy, origCopy.second }); + } + } + + curr_stmt = curr_stmt->lexNext(); + } + } + } + } +} diff --git a/sapfor/experts/Sapfor_2017/_src/Transformations/replace_dist_arrays_in_io.h b/sapfor/experts/Sapfor_2017/_src/Transformations/replace_dist_arrays_in_io.h new file mode 100644 index 0000000..a9998ef --- /dev/null +++ b/sapfor/experts/Sapfor_2017/_src/Transformations/replace_dist_arrays_in_io.h @@ -0,0 +1,11 @@ +#pragma once + +#include "../ParallelizationRegions/ParRegions.h" +#include "../Utils/SgUtils.h" +#include "../Utils/errors.h" +#include "../GraphCall/graph_calls.h" + +void replaceDistributedArraysInIO(std::vector& regions, + const std::map>& allFuncInfo, + std::map>& SPF_messages, + std::map>>& newDeclsToInclude); \ No newline at end of file diff --git a/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h b/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h index f2e596b..7e44619 100644 --- a/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h +++ b/sapfor/experts/Sapfor_2017/_src/Utils/PassManager.h @@ -257,6 +257,8 @@ void InitPassesDependencies(map> &passDepsIn, set list({ REVERT_SUBST_EXPR_RD, CONVERT_LOOP_TO_ASSIGN }) <= Pass(RESOLVE_PAR_REGIONS); + list({ REVERT_SUBST_EXPR_RD, CONVERT_LOOP_TO_ASSIGN, FILL_PAR_REGIONS}) <= Pass(REMOVE_DIST_ARRAYS_FROM_IO); + Pass(REVERT_SUBST_EXPR_RD) <= Pass(EXPAND_EXTRACT_PAR_REGION); Pass(FILL_PAR_REGIONS) <= Pass(PRINT_PAR_REGIONS_ERRORS);