diff --git a/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp b/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp index 4cf9961..02c7035 100644 --- a/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp +++ b/src/Transformations/ReplaceArraysInIO/replace_dist_arrays_in_io.cpp @@ -17,6 +17,144 @@ using std::pair; #define DEBUG_TRACE 0 +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 switchToDeclarationFile(DIST::Array* array_p, + pair& decl_place, + const string ¤t_file_name, + FuncInfo *current_func) +{ + if (!array_p) + return false; + + // try to find declaration from current function + for (const auto &p : array_p->GetDeclInfo()) + { + if (p.first == current_file_name && + current_func->linesNum.first <= p.second && + p.second <= current_func->linesNum.second) + { + decl_place = p; + return true; + } + } + + for (const auto &p : array_p->GetDeclInfo()) + { + if (SgFile::switchToFile(p.first) != -1) + { + decl_place = p; + return true; + } + } + + return false; +} + +static bool checkAssumedShape(SgStatement* decl, const string& array_name) +{ + SgExpression* list = decl->expr(0); + SgExpression* dim_list = NULL; + + while (list) + { + auto *arr_ref = list->lhs(); + + if (arr_ref && + arr_ref->symbol() && + arr_ref->symbol()->identifier() && + arr_ref->symbol()->identifier() == array_name) + { + dim_list = arr_ref->lhs(); + break; + } + + list = list->rhs(); + } + + if (!dim_list) + { + auto *dim_expr = findExprWithVariant(decl->expr(2), DIMENSION_OP); + if (dim_expr) + dim_list = dim_expr->lhs(); + } + + while (dim_list) + { + auto *lhs = dim_list->lhs(); + + if (lhs && lhs->variant() == DDOT && (!lhs->lhs() || !lhs->rhs())) + return true; + + dim_list = dim_list->rhs(); + } + + return false; +} + +static bool checkAssumedSize(const string &array_name, DIST::Array* array_p, const string ¤t_file_name, FuncInfo *current_func) +{ + if (!array_p) + return true; // raise true to prevent array from copying + + bool found = false; + + pair decl_place; + + if (!switchToDeclarationFile(array_p, decl_place, current_file_name, current_func)) + return true; + + auto *st = SgStatement::getStatementByFileAndLine(decl_place.first, decl_place.second); + checkNull(st, convertFileName(__FILE__).c_str(), __LINE__); + + SgExpression* list = st->expr(0); + while (list) + { + if (list->lhs() && + list->lhs()->symbol() && + list->lhs()->symbol()->identifier() && + list->lhs()->symbol()->identifier() == array_name + ) + { + if(findExprWithVariant(list->lhs(), STAR_RANGE)) + found = true; + + break; + } + + list = list->rhs(); + } + + if (!found) + { + auto *dim_expr = findExprWithVariant(st->expr(2), DIMENSION_OP); + if (dim_expr && findExprWithVariant(dim_expr, STAR_RANGE)) + found = true; + } + + if (SgFile::switchToFile(current_file_name) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); // can't switch back to file with array usage + + return found; +} + static void findArrays(SgExpression* exp, set& arrays) { if (exp) @@ -29,7 +167,10 @@ 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_name, + FuncInfo *current_func) { auto var = stat->variant(); @@ -112,6 +253,7 @@ static void populateDistributedIoArrays(map>& array spec = spec->rhs(); } } + break; } default: break; @@ -130,8 +272,15 @@ 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) - __spf_print(DEBUG_TRACE, "[%d]: add array %s\n", stat->lineNumber(), array_p->GetName().c_str()); + if (array_p && + array_p->GetDistributeFlagVal() == Distribution::distFlag::IO_PRIV && + !checkAssumedSize(array_name, array_p, current_file_name, current_func)) + { + auto inserted = arrays[by_symb].insert(stat).second; + + if (inserted) + __spf_print(DEBUG_TRACE, "[%d]: add array %s %p\n", stat->lineNumber(), array_p->GetName().c_str(), by_symb); + } } __spf_print(DEBUG_TRACE, "[replace]\n"); @@ -204,7 +353,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(); @@ -223,10 +377,23 @@ static void copyArrayBetweenStatements(SgSymbol* replace_symb, SgSymbol* replace auto* parent = start_is_scope ? start : start->controlParent(); if (parent && parent->lastNodeOfStmt() == start) parent = parent->controlParent(); + checkNull(parent, convertFileName(__FILE__).c_str(), __LINE__); 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 +404,14 @@ 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) { - 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 +478,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); } } @@ -347,9 +519,9 @@ static bool ioReginBorder(SgStatement* stat, SgStatement* last_io_bound) } void replaceDistributedArraysInIO(vector& regions, - const map>& allFuncInfo, - map>& SPF_messages, - map>>& newDeclsToInclude) + const map>& allFuncInfo, + map>& SPF_messages, + map>>& newDeclsToInclude) { map created_copies; map>> copied_syms; @@ -358,23 +530,29 @@ void replaceDistributedArraysInIO(vector& regions, { __spf_print(DEBUG_TRACE, "[%s]: enter region\n", region->GetName().c_str()); - for (auto& linesByFile : region->GetAllLinesToModify()) + for (auto& lines_by_file : region->GetAllLinesToModify()) { - const auto& filename = linesByFile.first; + const auto& current_file_name = lines_by_file.first; - if (SgFile::switchToFile(filename) == -1) + if (SgFile::switchToFile(current_file_name) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - for (auto& lines : linesByFile.second) + auto func_info_it = allFuncInfo.find(current_file_name); + if (func_info_it == allFuncInfo.end()) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto *lbound_symb = new SgSymbol(FUNCTION_NAME, "lbound"); + auto *ubound_symb = new SgSymbol(FUNCTION_NAME, "ubound"); + + for (auto& lines : lines_by_file.second) { - __spf_print(DEBUG_TRACE, "[fragment] %s: %d:%d %d\n", filename.c_str(), lines.lines.first, + __spf_print(DEBUG_TRACE, "[fragment] %s: %d:%d %d\n", current_file_name.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); @@ -390,6 +568,7 @@ void replaceDistributedArraysInIO(vector& regions, map> need_replace; SgStatement* last_io_bound = NULL; + FuncInfo *current_func_info = NULL; while (curr_stmt != end) { @@ -398,9 +577,21 @@ 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__); + curr_stmt = curr_stmt->lexNext(); while (curr_stmt && !isSgExecutableStatement(curr_stmt)) { @@ -424,78 +615,193 @@ void replaceDistributedArraysInIO(vector& regions, string array_name = string(array_to_copy->identifier()); DIST::Array* array_p = getArrayFromDeclarated(declaratedInStmt(array_to_copy), array_name); - bool fromModule = (array_p->GetLocation().first == DIST::l_MODULE); - const string locationName = array_p->GetLocation().second; + // at this point all considered arrays must have DIST::Array* references + if (!array_p) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + // ... and be declared in switchable files (not in headers) + pair decl_place; + if (!switchToDeclarationFile(array_p, decl_place, current_file_name, current_func_info)) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); - auto place = *array_p->GetDeclInfo().begin(); - string fileName = place.first; string suffix = "_io_l"; - if (fromModule) - suffix = "_io_m"; - - pair copied; - copied.first = array_to_copy; - - if (SgFile::switchToFile(fileName) == -1) + switch (array_p->GetLocation().first) { - auto* func_stmt = curr_stmt->getScopeForDeclare(); + case DIST::l_MODULE: + suffix = "_io_m"; + break; + case DIST::l_COMMON: + suffix = "_io_c"; + break; + } + + auto copied_symbol = copyArray(decl_place, + array_p, + lines_by_file.second, + suffix + to_string(region->GetId()), + decl_place.first, + newDeclsToInclude, + copied_syms); + - SgStatement* insertPlace = NULL; + // original declaration statement + auto *decl_stmt = SgStatement::getStatementByFileAndLine(decl_place.first, decl_place.second); + + if (!decl_stmt || !isSgDeclarationStatement(decl_stmt)) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + auto dynamic_array = checkAssumedShape(decl_stmt, array_name); + + while (decl_stmt && !isSgExecutableStatement(decl_stmt)) + { + if (isSgDeclarationStatement(decl_stmt) && + decl_stmt->expr(0) && + decl_stmt->expr(0)->lhs() && + decl_stmt->expr(0)->lhs()->symbol() == copied_symbol.second) + { + break; + } + + decl_stmt = decl_stmt->lexNext(); + } + + // created declaration statement + if (!decl_stmt || !isSgDeclarationStatement(decl_stmt)) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + // insert !$SPF ANALYSIS(PROCESS_PRIVATE(array)) directive before declaration statement + + string dir_str; + if (decl_stmt->comments()) + { + auto str_comment = string(decl_stmt->comments()); + if (str_comment.size() && str_comment.back() != '\n') + dir_str += "\n"; + } + + dir_str += "!$SPF ANALYSIS(PROCESS_PRIVATE(" + string(copied_symbol.second->identifier()) + "))\n"; + decl_stmt->addComment(dir_str.c_str()); + + created_copies.insert({ array_to_copy, copied_symbol.second }); + + // make array copy allocatable in case of assumed-shape array + if(dynamic_array) + { + // insert allocatable keyword in declaration + auto *kword_list = decl_stmt->expr(2); + if (!findExprWithVariant(kword_list, ALLOCATABLE_OP)) + { + if (!kword_list) + { + kword_list = new SgExprListExp(); + decl_stmt->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)); + } + + // can't switch back to file with array usage + if (SgFile::switchToFile(current_file_name) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + // insert allocate(a_l(lbound(a, 1):ubound(a,1),...)) statement + SgStatement* allocate_stmt_place = 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 && !isSgExecutableStatement(iterator); iterator = iterator->lexNext()) { - insertPlace = iterator; + allocate_stmt_place = iterator; } //NULL - no decl stats in function! - if (!insertPlace) - insertPlace = func_stmt; + if (!allocate_stmt_place) + allocate_stmt_place = func_stmt; - auto st = insertPlace->controlParent(); - if (st->variant() == GLOBAL) - st = insertPlace; + auto *allocate_stmt_parent = allocate_stmt_place->controlParent(); + if (allocate_stmt_parent->variant() == GLOBAL) + allocate_stmt_parent = allocate_stmt_place; + + auto *created_array_ref = new SgArrayRefExp(*copied_symbol.second); - auto& copied_symb = array_to_copy->copy(); - copied.second = &copied_symb; - - auto new_name = string(array_to_copy->identifier()) + "_io_c"; - copied_symb.changeName(new_name.c_str()); - - auto stat = array_to_copy->makeVarDeclStmt(); - auto res = CalculateInteger(stat->expr(0)->copyPtr()); - res->lhs()->setSymbol(copied_symb); - stat->setExpression(0, res); - - insertPlace->insertStmtAfter(*stat, *st); - } - else - copied = copyArray(place, array_p, linesByFile.second, suffix + to_string(region->GetId()), fileName, newDeclsToInclude, copied_syms); - - SgStatement* decl = SgStatement::getStatementByFileAndLine(place.first, place.second); - - if (decl) - decl = decl->lexNext(); - - if (decl) - { - string dir_str; - if (decl->comments()) + 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++) { - string str_comment = string(decl->comments()); - if (str_comment.size() && str_comment.back() != '\n') - dir_str += "\n"; + 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; + } } - 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 }); + auto *allocate_stmt = new SgStatement(ALLOCATE_STMT); + allocate_stmt->setExpression(0, created_array_ref); - if (curr_stmt->switchToFile() == -1) - printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + allocate_stmt_place->insertStmtAfter(*allocate_stmt, *allocate_stmt_parent); + + // 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()) + { + 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_symbol.second)); + + find_return_stmt->insertStmtAfter(*dealloc_stmt, *next->controlParent()); + + if (next == curr_stmt) + curr_stmt = dealloc_stmt; + } + + find_return_stmt = next; + } + } + + // can't switch back to file with array usage + if (SgFile::switchToFile(current_file_name) == -1) + printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } } @@ -507,7 +813,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); else printInternalError(convertFileName(__FILE__).c_str(), __LINE__); } @@ -527,7 +833,7 @@ void replaceDistributedArraysInIO(vector& regions, } } - populateDistributedIoArrays(need_replace, curr_stmt); + populateDistributedIoArrays(need_replace, curr_stmt, current_file_name, current_func_info); curr_stmt = curr_stmt->lexNext(); } } diff --git a/src/Utils/version.h b/src/Utils/version.h index 97027fe..e2700aa 100644 --- a/src/Utils/version.h +++ b/src/Utils/version.h @@ -1,3 +1,3 @@ #pragma once -#define VERSION_SPF "2443" +#define VERSION_SPF "2444"