From b5c923193cef6aef5b7bc5523c3963f023f866b1 Mon Sep 17 00:00:00 2001 From: xnpster Date: Sun, 17 Aug 2025 15:49:32 +0300 Subject: [PATCH] REMOVE_DIST_ARRAYS_FROM_IO: handle assumed-size and assumed-shape arrays --- .../replace_dist_arrays_in_io.cpp | 281 +++++++++++++++++- 1 file changed, 266 insertions(+), 15 deletions(-) diff --git a/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp b/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp index 4cf9961..a6df223 100644 --- a/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp +++ b/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp @@ -17,6 +17,86 @@ using std::pair; #define DEBUG_TRACE 0 +static bool findAlloatableKeyword(SgExpression* exp) +{ + if (exp) + { + if (exp->variant() == ALLOCATABLE_OP) + return true; + + return findAlloatableKeyword(exp->lhs()) || findAlloatableKeyword(exp->rhs()); + } + + return false; +} + + +static bool checkDynamicArray(DIST::Array *array) +{ + for (const auto &bounds : array->GetSizes()) + if (bounds.first == -1 || bounds.second == -1) + return true; + + return false; +} + +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 bool checkAssumedSize(SgStatement *st, const string &arrayName, const string ¤tFile) +{ + __spf_print(1, "Try array %s\n", arrayName.c_str()); + bool found = false; + + DIST::Array* array_p = getArrayFromDeclarated(st, arrayName); + + auto place = *array_p->GetDeclInfo().begin(); + auto decl_file_name = place.first; + + SgFile::switchToFile(decl_file_name); + + SgExpression* list = st->expr(0); + while (list) + { + __spf_print(1, "Try list %s\n", list->lhs()->unparse()); + + if (list->lhs() && list->lhs()->symbol()->identifier() == arrayName) + { + if(findExprWithVariant(list->lhs(), STAR_RANGE)) + found = true; + + break; + } + } + + if (!found) + { + auto *dim_expr = findExprWithVariant(st->expr(2), DIMENSION_OP); + if (dim_expr && findExprWithVariant(dim_expr, STAR_RANGE)) + found = true; + } + + SgFile::switchToFile(currentFile); + + return found; +} + static void findArrays(SgExpression* exp, set& arrays) { if (exp) @@ -29,7 +109,7 @@ static void findArrays(SgExpression* exp, set& arrays) } } -static void populateDistributedIoArrays(map>& arrays, SgStatement* stat) +static void populateDistributedIoArrays(map>& arrays, SgStatement* stat, const string& current_file) { auto var = stat->variant(); @@ -130,8 +210,14 @@ static void populateDistributedIoArrays(map>& array { string array_name = string(by_symb->identifier()); DIST::Array* array_p = getArrayFromDeclarated(declaratedInStmt(by_symb), array_name); - if (array_p && array_p->GetDistributeFlagVal() == Distribution::distFlag::IO_PRIV && arrays[by_symb].insert(stat).second) + if (array_p && + array_p->GetDistributeFlagVal() == Distribution::distFlag::IO_PRIV && + !checkAssumedSize(declaratedInStmt(by_symb), array_name, current_file) && + arrays[by_symb].insert(stat).second + ) + { __spf_print(DEBUG_TRACE, "[%d]: add array %s\n", stat->lineNumber(), array_p->GetName().c_str()); + } } __spf_print(DEBUG_TRACE, "[replace]\n"); @@ -204,7 +290,12 @@ static void replaceArrayRec(SgSymbol* arr, SgSymbol* replace_by, SgStatement* st } } -static void copyArrayBetweenStatements(SgSymbol* replace_symb, SgSymbol* replace_by, SgStatement* start, SgStatement* last, bool start_is_scope) +static void copyArrayBetweenStatements(SgSymbol* replace_symb, + SgSymbol* replace_by, + SgStatement* start, + SgStatement* last, + bool start_is_scope, + FuncInfo *func_info) { while (start->lexNext() && !isSgExecutableStatement(start->lexNext())) start = start->lexNext(); @@ -227,6 +318,18 @@ static void copyArrayBetweenStatements(SgSymbol* replace_symb, SgSymbol* replace start->insertStmtAfter(*assign, *parent); } + if (has_write) + { + for (int i = 0; i < func_info->funcParams.identificators.size(); i++) + { + if (func_info->funcParams.identificators[i] == replace_symb->identifier()) + { + has_write &= func_info->funcParams.isArgOut(i); + break; + } + } + } + if (has_write) { // A = A_reg @@ -237,9 +340,15 @@ static void copyArrayBetweenStatements(SgSymbol* replace_symb, SgSymbol* replace } } -static void replaceArrayInFragment(SgSymbol* replace_symb, const set usages, SgSymbol* replace_by, SgStatement* start, SgStatement* last, const string& filename) +static void replaceArrayInFragment(SgSymbol* replace_symb, + const set usages, + SgSymbol* replace_by, + SgStatement* start, + SgStatement* last, + FuncInfo *func_info, + const string& filename) { - while (start->lexNext() && !isSgExecutableStatement(start->lexNext())) + while (start->lexNext() && (!isSgExecutableStatement(start->lexNext()) || start->lexNext()->variant() == ALLOCATE_STMT)) start = start->lexNext(); set not_opened, not_closed, copied; @@ -306,7 +415,7 @@ static void replaceArrayInFragment(SgSymbol* replace_symb, const setidentifier(), scope_start->lineNumber(), scope_end->lineNumber()); - copyArrayBetweenStatements(replace_symb, replace_by, scope_start, scope_end, copy_scope == scope_start); + copyArrayBetweenStatements(replace_symb, replace_by, scope_start, scope_end, copy_scope == scope_start, func_info); copied.insert(copy_scope); } } @@ -365,6 +474,16 @@ void replaceDistributedArraysInIO(vector& regions, if (SgFile::switchToFile(filename) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + auto func_info_it = allFuncInfo.find(filename); + if (func_info_it == allFuncInfo.end()) + { + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + return; + } + + auto *lbound_symb = new SgSymbol(PROCEDURE_NAME, "lbound"); + auto *ubound_symb = new SgSymbol(PROCEDURE_NAME, "ubound"); + for (auto& lines : linesByFile.second) { __spf_print(DEBUG_TRACE, "[fragment] %s: %d:%d %d\n", filename.c_str(), lines.lines.first, @@ -374,7 +493,6 @@ void replaceDistributedArraysInIO(vector& regions, if (lines.isImplicit()) { - curr_stmt = current_file->SgStatementAtLine(lines.lines.first); end = current_file->SgStatementAtLine(lines.lines.second); @@ -390,6 +508,7 @@ void replaceDistributedArraysInIO(vector& regions, map> need_replace; SgStatement* last_io_bound = NULL; + FuncInfo *current_func_info = NULL; while (curr_stmt != end) { @@ -398,9 +517,24 @@ void replaceDistributedArraysInIO(vector& regions, auto var = curr_stmt->variant(); - 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__); + return; + } + curr_stmt = curr_stmt->lexNext(); while (curr_stmt && !isSgExecutableStatement(curr_stmt)) { @@ -428,7 +562,7 @@ void replaceDistributedArraysInIO(vector& regions, const string locationName = array_p->GetLocation().second; auto place = *array_p->GetDeclInfo().begin(); - string fileName = place.first; + auto decl_file_name = place.first; string suffix = "_io_l"; if (fromModule) @@ -437,7 +571,7 @@ void replaceDistributedArraysInIO(vector& regions, pair copied; copied.first = array_to_copy; - if (SgFile::switchToFile(fileName) == -1) + if (SgFile::switchToFile(decl_file_name) == -1) { auto* func_stmt = curr_stmt->getScopeForDeclare(); @@ -472,7 +606,9 @@ void replaceDistributedArraysInIO(vector& regions, insertPlace->insertStmtAfter(*stat, *st); } else - copied = copyArray(place, array_p, linesByFile.second, suffix + to_string(region->GetId()), fileName, newDeclsToInclude, copied_syms); + { + copied = copyArray(place, array_p, linesByFile.second, suffix + to_string(region->GetId()), decl_file_name, newDeclsToInclude, copied_syms); + } SgStatement* decl = SgStatement::getStatementByFileAndLine(place.first, place.second); @@ -492,10 +628,125 @@ void replaceDistributedArraysInIO(vector& regions, dir_str += "!$SPF ANALYSIS(PROCESS_PRIVATE(" + string(copied.second->identifier()) + "))\n"; decl->addComment(dir_str.c_str()); } + created_copies.insert({ array_to_copy, copied.second }); - if (curr_stmt->switchToFile() == -1) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + // make array-copy allocatable in case of main array shape not constant + if(checkDynamicArray(array_p)) + { + // insert allocatable keyword in declaration + auto *kword_list = decl->expr(2); + if (!findAlloatableKeyword(kword_list)) + { + if (!kword_list) + { + kword_list = new SgExprListExp(); + decl->setExpression(2, *kword_list); + } + + while (kword_list->rhs()) + kword_list = kword_list->rhs(); + + if (kword_list->lhs()) + { + kword_list->setRhs(new SgExprListExp()); + kword_list = kword_list->rhs(); + } + + kword_list->setLhs(new SgExpression(ALLOCATABLE_OP)); + } + + // insert allocate(a_l(lbound(a, 1):ubound(a,1),...)) statement + SgFile::switchToFile(filename); + SgStatement* insertPlace = NULL; + + auto* func_stmt = curr_stmt->getScopeForDeclare(); + for (auto iterator = func_stmt->lexNext(); + !isSgExecutableStatement(iterator) || isSPF_stat(iterator) && + !(iterator->variant() == SPF_PARALLEL_REG_DIR || iterator->variant() == SPF_END_PARALLEL_REG_DIR); + iterator = iterator->lexNext()) + { + insertPlace = iterator; + } + + //NULL - no decl stats in function! + if (!insertPlace) + insertPlace = func_stmt; + + auto st = insertPlace->controlParent(); + if (st->variant() == GLOBAL) + st = insertPlace; + + auto *stat = new SgStatement(ALLOCATE_STMT); + auto *created_array_ref = new SgArrayRefExp(*copied.second); + + auto* dim_list = new SgExprListExp(); + created_array_ref->setLhs(dim_list); + + int dim_len = array_p->GetSizes().size(); + for (int i = 1; i <= dim_len; i++) + { + auto *lcall = new SgFunctionCallExp(*lbound_symb); + auto *rcall = new SgFunctionCallExp(*ubound_symb); + + for (auto *call : {lcall, rcall}) + { + call->setLhs(new SgExprListExp()); + + call->lhs()->setLhs(new SgArrayRefExp(*array_to_copy)); + call->lhs()->setRhs(new SgValueExp(i)); + } + + auto *dot_expr = new SgExpression(DDOT); + dot_expr->setLhs(lcall); + dot_expr->setRhs(rcall); + + dim_list->setLhs(dot_expr); + + if (i < dim_len) + { + auto *next = new SgExprListExp(); + dim_list->setRhs(next); + dim_list = next; + } + } + + stat->setExpression(0, created_array_ref); + + insertPlace->insertStmtAfter(*stat, *st); + + // insert deallocate statemens before all returns + auto *find_return_stmt = func_stmt; + while (find_return_stmt != func_stmt->lastNodeOfStmt()) + { + auto *next = find_return_stmt->lexNext(); + if (next && (isSgReturnStmt(next) || next == func_stmt->lastNodeOfStmt())) + { + if (next->hasLabel()) + { + __spf_print(1, "%s has label\n", next->unparse()); + moveLabelBefore(next); + find_return_stmt = next->lexPrev(); + } + + auto *dealloc_stmt = new SgStatement(DEALLOCATE_STMT); + + dealloc_stmt->setExpression(0, new SgExprListExp()); + dealloc_stmt->expr(0)->setLhs(new SgArrayRefExp(*copied.second)); + + find_return_stmt->insertStmtAfter(*dealloc_stmt, *next->controlParent()); + + if (next == curr_stmt) + curr_stmt = dealloc_stmt; + } + + find_return_stmt = next; + } + } + + SgFile::switchToFile(filename); + + } } @@ -507,7 +758,7 @@ void replaceDistributedArraysInIO(vector& regions, { 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); + replaceArrayInFragment(p.first, p.second, it->second, last_io_bound, curr_stmt, current_func_info, filename); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } @@ -527,7 +778,7 @@ void replaceDistributedArraysInIO(vector& regions, } } - populateDistributedIoArrays(need_replace, curr_stmt); + populateDistributedIoArrays(need_replace, curr_stmt, filename); curr_stmt = curr_stmt->lexNext(); } }