diff --git a/.gitignore b/.gitignore index d9bf98a..0957d80 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,4 @@ Sapfor/Sapc++/x64/ Sapfor/out/ Sapfor/_bin/* +_bin/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 580342b..12e61a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -207,7 +207,9 @@ set(TR_EXPR_TRANSFORM src/Transformations/ExpressionSubstitution/control_flow_gr set(TR_INLINER src/Transformations/FunctionInlining/inliner.cpp src/Transformations/FunctionInlining/inliner.h) set(TR_RENAME_SYMBOLS src/Transformations/RenameSymbols/rename_symbols.cpp - src/Transformations/RenameSymbols/rename_symbols.h) + src/Transformations/RenameSymbols/rename_symbols.h) +SET(TR_MOVE_OPERATORS src/Transformations/MoveOperators/move_operators.cpp + src/Transformations/MoveOperators/move_operators.h) set(TRANSFORMS ${TR_DEAD_CODE} @@ -230,7 +232,8 @@ set(TRANSFORMS ${TR_REPLACE_ARRAYS_IN_IO} ${TR_EXPR_TRANSFORM} ${TR_INLINER} - ${TR_RENAME_SYMBOLS}) + ${TR_RENAME_SYMBOLS} + ${TR_MOVE_OPERATORS}) set(CFG src/CFGraph/IR.cpp src/CFGraph/IR.h @@ -464,6 +467,7 @@ 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 (Transformations\\MoveOperators FILES ${TR_MOVE_OPERATORS}) source_group (CreateIntervals FILES ${CREATE_INTER_T}) diff --git a/src/Sapfor.cpp b/src/Sapfor.cpp index d37f078..7baa9b8 100644 --- a/src/Sapfor.cpp +++ b/src/Sapfor.cpp @@ -90,6 +90,7 @@ #include "Transformations/DeadCodeRemoving/dead_code.h" #include "Transformations/RenameSymbols/rename_symbols.h" #include "Transformations/FunctionInlining/inliner.h" +#include "Transformations/MoveOperators/move_operators.h" #include "ProjectParameters/projectParameters.h" @@ -941,6 +942,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne internalExit = err; } } + else if (curr_regime == MOVE_OPERATORS) + moveOperators(file, loopGraph, fullIR, countOfTransform); else if (curr_regime == PRIVATE_REMOVING_ANALYSIS) { auto itFound = loopGraph.find(file->filename()); @@ -1037,7 +1040,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne PRIVATE_REMOVING, PRIVATE_ARRAYS_EXPANSION, PRIVATE_ARRAYS_SHRINKING, - REMOVE_DEAD_CODE }; + REMOVE_DEAD_CODE, + MOVE_OPERATORS }; if ((countOfTransform == 0 || internalExit > 0) && applyFor.find(curr_regime) != applyFor.end()) { @@ -2339,6 +2343,7 @@ void runPass(const int curr_regime, const char *proj_name, const char *folderNam case INSERT_NO_DISTR_FLAGS_FROM_GUI: case PRIVATE_REMOVING: case RENAME_INLCUDES: + case MOVE_OPERATORS: runAnalysis(*project, curr_regime, true, "", folderName); break; case INLINE_PROCEDURES: diff --git a/src/Sapfor.h b/src/Sapfor.h index 7f21c22..f5dadd1 100644 --- a/src/Sapfor.h +++ b/src/Sapfor.h @@ -122,6 +122,8 @@ enum passes { CREATE_INTER_TREE, INSERT_INTER_TREE, + MOVE_OPERATORS, + SHADOW_GROUPING, INLINE_PROCEDURES, FILL_PARALLEL_REG_IR, @@ -321,6 +323,7 @@ static void setPassValues() passNames[CHECK_PAR_REG_DIR] = "CHECK_PAR_REG_DIR"; passNames[CREATE_INTER_TREE] = "CREATE_INTER_TREE"; passNames[INSERT_INTER_TREE] = "INSERT_INTER_TREE"; + passNames[MOVE_OPERATORS] = "MOVE_OPERATORS"; passNames[CREATE_PARALLEL_REGIONS] = "CREATE_PARALLEL_REGIONS"; passNames[PRIVATE_REMOVING_ANALYSIS] = "PRIVATE_REMOVING_ANALYSIS"; passNames[PRIVATE_REMOVING] = "PRIVATE_REMOVING"; diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp new file mode 100644 index 0000000..d310afe --- /dev/null +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -0,0 +1,826 @@ +#include +#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; + +static vector findInstructionsFromOperator(SgStatement* st, const vector& Blocks) { + vector result; + string filename = st->fileName(); + + for (auto& block: Blocks) { + vector instructionsInBlock = block->getInstructions(); + + for (auto& instruction: instructionsInBlock) { + SgStatement* curOperator = instruction->getInstruction()->getOperator(); + if (curOperator->lineNumber() == st->lineNumber()) + result.push_back(instruction); + } + } + return result; +} + +const unordered_set loop_tags = { FOR_NODE }; +const unordered_set control_tags = { IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE }; +const unordered_set control_end_tags = { CONTROL_END }; + +struct OperatorInfo { + SgStatement* stmt; + set usedVars; + set definedVars; + int lineNumber; + bool isMovable; + + OperatorInfo(SgStatement* s) : stmt(s), lineNumber(s->lineNumber()), isMovable(true) { } +}; + +static bool isStatementEmbedded(SgStatement* stmt, SgStatement* parent) { + if (!stmt || !parent || stmt == parent) + return false; + + if (parent->variant() == LOGIF_NODE) { + if (stmt->lineNumber() == parent->lineNumber()) + return true; + + SgStatement* current = parent; + SgStatement* lastNode = parent->lastNodeOfStmt(); + + while (current && current != lastNode) { + if (current == stmt) + return true; + + if (current->isIncludedInStmt(*stmt)) + return true; + + current = current->lexNext(); + } + } + + if (parent->isIncludedInStmt(*stmt)) + return true; + + return false; +} + +static bool isLoopBoundary(SgStatement* stmt) { + if (!stmt) + return false; + + if (stmt->variant() == FOR_NODE || stmt->variant() == CONTROL_END) + return true; + + return false; +} + +static bool isPartOfNestedLoop(SgStatement* stmt, SgForStmt* loop) { + if (!stmt || !loop) + return false; + + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + if (!loopStart || !loopEnd) + return false; + + if (stmt->lineNumber() < loopStart->lineNumber() || stmt->lineNumber() > loopEnd->lineNumber()) + return false; + + SgStatement* current = loopStart; + + while (current && current != loopEnd) { + + if (current->variant() == FOR_NODE && current != loop) { + SgForStmt* nestedLoop = (SgForStmt*)current; + SgStatement* nestedStart = nestedLoop->lexNext(); + SgStatement* nestedEnd = nestedLoop->lastNodeOfStmt(); + + if (nestedStart && nestedEnd && + stmt->lineNumber() >= nestedStart->lineNumber() && + stmt->lineNumber() <= nestedEnd->lineNumber()) { + return true; + } + } + + current = current->lexNext(); + } + + return false; +} + +static bool canSafelyExtract(SgStatement* stmt, SgForStmt* loop) { + if (!stmt || !loop) + return false; + + if (isLoopBoundary(stmt)) + return false; + + if (control_tags.find(stmt->variant()) != control_tags.end()) + return false; + + if (isPartOfNestedLoop(stmt, loop)) + return false; + + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + if (!loopStart || !loopEnd) + return false; + + SgStatement* current = loopStart; + + while (current && current != loopEnd) { + if (current->variant() == LOGIF_NODE && current->lineNumber() == stmt->lineNumber()) + return false; + + if (control_tags.find(current->variant()) != control_tags.end()) + if (isStatementEmbedded(stmt, current)) + return false; + + if (current == stmt) + break; + current = current->lexNext(); + } + + return true; +} + +static vector analyzeOperatorsInLoop(SgForStmt* loop, const vector& blocks, + const map>& FullIR) { + vector operators; + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + + if (!loopStart || !loopEnd) + return operators; + + SgStatement* current = loopStart; + unordered_set visited; + + while (current && current != loopEnd) { + + if (visited.find(current) != visited.end()) + break; + + visited.insert(current); + + if (isLoopBoundary(current)) { + current = current->lexNext(); + continue; + } + + if (current->variant() == FOR_NODE && current != loop) { + SgStatement* nestedEnd = current->lastNodeOfStmt(); + if (nestedEnd) + current = nestedEnd->lexNext(); + else + current = current->lexNext(); + continue; + } + + if (isSgExecutableStatement(current)) { + if (control_tags.find(current->variant()) != control_tags.end()) { + current = current->lexNext(); + continue; + } + + if (current->variant() != ASSIGN_STAT) { + current = current->lexNext(); + continue; + } + + OperatorInfo opInfo(current); + + vector irBlocks = findInstructionsFromOperator(current, blocks); + for (auto irBlock : irBlocks) { + if (!irBlock || !irBlock->getInstruction()) + continue; + + const SAPFOR::Instruction* instr = irBlock->getInstruction(); + if (instr->getArg1()) { + string varName = getNameByArg(instr->getArg1()); + if (!varName.empty()) + opInfo.usedVars.insert(varName); + } + + if (instr->getArg2()) { + string varName = getNameByArg(instr->getArg2()); + if (!varName.empty()) + opInfo.usedVars.insert(varName); + } + + if (instr->getResult()) { + string varName = getNameByArg(instr->getResult()); + if (!varName.empty()) + opInfo.definedVars.insert(varName); + } + } + + operators.push_back(opInfo); + } + current = current->lexNext(); + } + + return operators; +} + +static map> findVariableDefinitions(SgForStmt* loop, vector& operators) { + map> varDefinitions; + for (auto& op : operators) + for (const string& var : op.definedVars) + varDefinitions[var].push_back(op.stmt); + + return varDefinitions; +} + +static int calculateDistance(SgStatement* from, SgStatement* to) { + if (!from || !to) + return INT_MAX; + + return abs(to->lineNumber() - from->lineNumber()); +} + +static SgStatement* findBestPosition(SgStatement* operatorStmt, const vector& operators, + const map>& varDefinitions, SgForStmt* loop) { + const OperatorInfo* opInfo = nullptr; + for (auto& op : operators) { + if (op.stmt == operatorStmt) { + opInfo = &op; + break; + } + } + + if (!opInfo || !opInfo->isMovable) + return nullptr; + + SgStatement* bestPos = nullptr; + int bestLine = -1; + + for (const string& usedVar : opInfo->usedVars) { + if (varDefinitions.find(usedVar) != varDefinitions.end()) { + for (SgStatement* defStmt : varDefinitions.at(usedVar)) { + if (defStmt->lineNumber() < operatorStmt->lineNumber()) { + if (defStmt->controlParent() == operatorStmt->controlParent()) { + if (defStmt->lineNumber() > bestLine) { + bestLine = defStmt->lineNumber(); + bestPos = defStmt; + } + } + } + } + } + } + + if (!bestPos) { + bool allLoopCarried = true; + bool hasAnyDefinition = false; + + for (const string& usedVar : opInfo->usedVars) { + if (varDefinitions.find(usedVar) != varDefinitions.end()) { + for (SgStatement* defStmt : varDefinitions.at(usedVar)) { + if (defStmt == operatorStmt) + continue; + + hasAnyDefinition = true; + if (defStmt->lineNumber() < operatorStmt->lineNumber() && + defStmt->controlParent() == operatorStmt->controlParent()) { + allLoopCarried = false; + break; + } + } + } + + if (!allLoopCarried) + break; + } + + if (allLoopCarried || (!hasAnyDefinition && !opInfo->usedVars.empty())) { + SgStatement* loopStart = loop->lexNext(); + return loopStart; + } + } + + return bestPos; +} + +static bool canMoveTo(SgStatement* from, SgStatement* to, SgForStmt* loop) { + if (!from || !to || from == to) + return false; + + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + + if (!loopStart || !loopEnd) + return false; + + if (to == loopStart) { + SgStatement* fromControlParent = from->controlParent(); + if (!fromControlParent) fromControlParent = loop; + return fromControlParent == loop || fromControlParent == loopStart->controlParent(); + } + + if (from->lineNumber() < loopStart->lineNumber() || from->lineNumber() > loopEnd->lineNumber()) + return false; + + if (to->lineNumber() < loopStart->lineNumber() || to->lineNumber() > loopEnd->lineNumber()) + return false; + + if (to->lineNumber() >= from->lineNumber()) + return false; + + if (from->controlParent() != to->controlParent()) + return false; + + SgStatement* current = to->lexNext(); + while (current && current != from && current != loopEnd) { + if (control_tags.find(current->variant()) != control_tags.end()) { + SgStatement* controlEnd = current->lastNodeOfStmt(); + if (controlEnd && from->lineNumber() <= controlEnd->lineNumber()) { + if (from->controlParent() == current && to->controlParent() != current) { + return false; + } + } + } + current = current->lexNext(); + } + + return true; +} + +static vector optimizeOperatorOrder(SgForStmt* loop, + const vector& operators, + const map>& varDefinitions) { + vector newOrder; + for (auto& op : operators) + newOrder.push_back(op.stmt); + + map stmtToOpInfo; + for (auto& op : operators) + stmtToOpInfo[op.stmt] = &op; + + bool changed = true; + + while (changed) { + changed = false; + + for (int i = operators.size() - 1; i >= 0; i--) { + if (!operators[i].isMovable) + continue; + + SgStatement* stmt = operators[i].stmt; + const OperatorInfo* opInfo = stmtToOpInfo[stmt]; + + if (!opInfo) + continue; + + size_t currentPos = 0; + for (size_t j = 0; j < newOrder.size(); j++) { + if (newOrder[j] == stmt) { + currentPos = j; + break; + } + } + + SgStatement* bestPos = findBestPosition(stmt, operators, varDefinitions, loop); + + if (!bestPos) { + bool hasDependents = false; + for (size_t j = currentPos + 1; j < newOrder.size(); j++) { + SgStatement* candidate = newOrder[j]; + const OperatorInfo* candidateOpInfo = stmtToOpInfo[candidate]; + if (candidateOpInfo) { + for (const string& definedVar : opInfo->definedVars) { + if (candidateOpInfo->usedVars.find(definedVar) != candidateOpInfo->usedVars.end()) { + hasDependents = true; + break; + } + } + + if (hasDependents) + break; + } + } + + continue; + } + + size_t targetPos = 0; + bool foundTarget = false; + + if (bestPos == loop->lexNext()) { + targetPos = 0; + + for (size_t j = 0; j < currentPos && j < newOrder.size(); j++) { + SgStatement* candidate = newOrder[j]; + const OperatorInfo* candidateOpInfo = stmtToOpInfo[candidate]; + if (candidateOpInfo) { + bool usesDefinedVar = false; + for (const string& definedVar : opInfo->definedVars) { + if (candidateOpInfo->usedVars.find(definedVar) != candidateOpInfo->usedVars.end()) { + usesDefinedVar = true; + break; + } + } + + if (usesDefinedVar) { + targetPos = j; + break; + } + } + } + + foundTarget = true; + + if (currentPos != targetPos && canMoveTo(stmt, bestPos, loop)) { + newOrder.erase(newOrder.begin() + currentPos); + newOrder.insert(newOrder.begin() + targetPos, stmt); + changed = true; + } + } else { + size_t bestPosIdx = 0; + bool foundBestPos = false; + for (size_t j = 0; j < newOrder.size(); j++) { + if (newOrder[j] == bestPos) { + bestPosIdx = j; + foundBestPos = true; + break; + } + } + + if (foundBestPos) { + targetPos = bestPosIdx + 1; + + for (size_t j = bestPosIdx + 1; j < currentPos && j < newOrder.size(); j++) { + SgStatement* candidate = newOrder[j]; + const OperatorInfo* candidateOpInfo = stmtToOpInfo[candidate]; + if (candidateOpInfo) { + bool definesUsedVar = false; + for (const string& usedVar : opInfo->usedVars) { + if (candidateOpInfo->definedVars.find(usedVar) != candidateOpInfo->definedVars.end()) { + definesUsedVar = true; + break; + } + } + if (definesUsedVar) + targetPos = j + 1; + } + } + + bool wouldBreakDependency = false; + for (size_t j = targetPos; j < currentPos && j < newOrder.size(); j++) { + SgStatement* candidate = newOrder[j]; + const OperatorInfo* candidateOpInfo = stmtToOpInfo[candidate]; + if (candidateOpInfo) { + for (const string& definedVar : opInfo->definedVars) { + if (candidateOpInfo->usedVars.find(definedVar) != candidateOpInfo->usedVars.end()) { + wouldBreakDependency = true; + break; + } + } + + if (wouldBreakDependency) + break; + } + } + + if (!wouldBreakDependency && currentPos > targetPos && canMoveTo(stmt, bestPos, loop)) { + newOrder.erase(newOrder.begin() + currentPos); + newOrder.insert(newOrder.begin() + targetPos, stmt); + changed = true; + } + } + } + } + } + + bool dependencyViolation = true; + set> triedPairs; + + while (dependencyViolation) { + dependencyViolation = false; + triedPairs.clear(); + + for (size_t i = 0; i < newOrder.size(); i++) { + SgStatement* stmt = newOrder[i]; + const OperatorInfo* opInfo = stmtToOpInfo[stmt]; + if (!opInfo) + continue; + + for (size_t j = 0; j < i; j++) { + SgStatement* prevStmt = newOrder[j]; + const OperatorInfo* prevOpInfo = stmtToOpInfo[prevStmt]; + if (!prevOpInfo) + continue; + + pair key = make_pair(stmt, prevStmt); + if (triedPairs.find(key) != triedPairs.end()) + continue; + + bool violation = false; + for (const string& definedVar : opInfo->definedVars) { + if (prevOpInfo->usedVars.find(definedVar) != prevOpInfo->usedVars.end()) { + violation = true; + break; + } + } + + if (violation) { + triedPairs.insert(key); + + bool wouldCreateViolation = false; + for (size_t k = j; k < i; k++) { + SgStatement* betweenStmt = newOrder[k]; + const OperatorInfo* betweenOpInfo = stmtToOpInfo[betweenStmt]; + + if (!betweenOpInfo) + continue; + + for (const string& usedVar : opInfo->usedVars) { + if (betweenOpInfo->definedVars.find(usedVar) != betweenOpInfo->definedVars.end()) { + wouldCreateViolation = true; + break; + } + } + + if (wouldCreateViolation) + break; + } + + if (!wouldCreateViolation) { + newOrder.erase(newOrder.begin() + i); + newOrder.insert(newOrder.begin() + j, stmt); + dependencyViolation = true; + break; + } + } + } + + if (dependencyViolation) + break; + } + } + + return newOrder; +} + +static bool applyOperatorReordering(SgForStmt* loop, const vector& newOrder) { + if (!loop || newOrder.empty()) + return false; + + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + + if (!loopStart || !loopEnd) + return false; + + vector originalOrder; + SgStatement* current = loopStart; + while (current && current != loopEnd) { + if (isSgExecutableStatement(current) && current->variant() == ASSIGN_STAT) + originalOrder.push_back(current); + + current = current->lexNext(); + } + + bool orderChanged = false; + if (originalOrder.size() == newOrder.size()) { + for (size_t i = 0; i < originalOrder.size(); i++) { + if (originalOrder[i] != newOrder[i]) { + orderChanged = true; + break; + } + } + } + else + orderChanged = true; + + if (!orderChanged) + return false; + + vector extractedStatements; + vector savedComments; + unordered_set extractedSet; + map originalLineNumbers; + map stmtToExtracted; + + for (SgStatement* stmt : newOrder) { + if (stmt && stmt != loop && stmt != loopEnd && extractedSet.find(stmt) == extractedSet.end()) { + if (control_tags.find(stmt->variant()) != control_tags.end()) + continue; + + if (!canSafelyExtract(stmt, loop)) + continue; + + bool isMoving = false; + for (size_t i = 0; i < originalOrder.size(); i++) { + if (originalOrder[i] == stmt) { + for (size_t j = 0; j < newOrder.size(); j++) { + if (newOrder[j] == stmt && i != j) { + isMoving = true; + break; + } + } + break; + } + } + + if (!isMoving) + continue; + + originalLineNumbers[stmt] = stmt->lineNumber(); + savedComments.push_back(stmt->comments() ? strdup(stmt->comments()) : nullptr); + SgStatement* extracted = stmt->extractStmt(); + if (extracted) { + extractedStatements.push_back(extracted); + extractedSet.insert(stmt); + stmtToExtracted[stmt] = extracted; + } + } + } + + map insertedStatements; + + for (size_t idx = 0; idx < newOrder.size(); idx++) { + SgStatement* stmt = newOrder[idx]; + + if (extractedSet.find(stmt) != extractedSet.end()) { + SgStatement* stmtToInsert = stmtToExtracted[stmt]; + + if (!stmtToInsert) + continue; + + SgStatement* insertAfter = loop; + + for (int i = idx - 1; i >= 0; i--) { + SgStatement* prevStmt = newOrder[i]; + + if (extractedSet.find(prevStmt) != extractedSet.end()) { + if (insertedStatements.find(prevStmt) != insertedStatements.end()) { + insertAfter = insertedStatements[prevStmt]; + break; + } + } else { + SgStatement* search = loop->lexNext(); + while (search && search != loopEnd) { + bool skip = false; + for (size_t j = idx; j < newOrder.size(); j++) { + if (extractedSet.find(newOrder[j]) != extractedSet.end() && + search == newOrder[j]) { + skip = true; + break; + } + } + if (skip) { + search = search->lexNext(); + continue; + } + + if (search == prevStmt) { + insertAfter = search; + break; + } + search = search->lexNext(); + } + if (insertAfter != loop) break; + } + } + + size_t commentIdx = 0; + for (size_t i = 0; i < extractedStatements.size(); i++) { + if (extractedStatements[i] == stmtToInsert) { + commentIdx = i; + break; + } + } + + if (commentIdx < savedComments.size() && savedComments[commentIdx]) + stmtToInsert->setComments(savedComments[commentIdx]); + + if (originalLineNumbers.find(stmt) != originalLineNumbers.end()) + stmtToInsert->setlineNumber(originalLineNumbers[stmt]); + + SgStatement* controlParent = stmt->controlParent(); + if (!controlParent) + controlParent = loop; + + insertAfter->insertStmtAfter(*stmtToInsert, *controlParent); + insertedStatements[stmt] = stmtToInsert; + } + } + + for (char* comment : savedComments) { + if (comment) + free(comment); + } + + return true; +} + +vector findFuncBlocksByFuncStatement(SgStatement *st, const map>& FullIR) { + vector result; + Statement* forSt = (Statement*)st; + + for (auto& func: FullIR) { + if (func.first->funcPointer->getCurrProcessFile() == forSt->getCurrProcessFile() + && func.first->funcPointer->lineNumber() == forSt->lineNumber()) + { + result = func.second; + } + } + return result; +} + +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(); + unordered_set blocks_nums; + + while (loopBody && loopBody != lastLoopNode) { + vector irBlocks = findInstructionsFromOperator(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 void processLoopRecursively(SgForStmt* loop, const vector& blocks, + const map>& FullIR) { + if (!loop) + return; + + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + if (loopStart && loopEnd) { + SgStatement* current = loopStart; + while (current && current != loopEnd) { + if (current->variant() == FOR_NODE && current != loop) { + SgForStmt* nestedLoop = (SgForStmt*)current; + processLoopRecursively(nestedLoop, blocks, FullIR); + SgStatement* nestedEnd = nestedLoop->lastNodeOfStmt(); + + if (nestedEnd) + current = nestedEnd->lexNext(); + else + current = current->lexNext(); + } + else + current = current->lexNext(); + } + } + + vector operators = analyzeOperatorsInLoop(loop, blocks, FullIR); + if (!operators.empty()) { + map> varDefinitions = findVariableDefinitions(loop, operators); + vector newOrder = optimizeOperatorOrder(loop, operators, varDefinitions); + applyOperatorReordering(loop, newOrder); + } +} + +void moveOperators(SgFile *file, map>& loopGraph, + const map>& FullIR, + int& countOfTransform) { + countOfTransform += 1; + + //cout << "MOVE_OPERATORS Pass Started" << endl; + + const int funcNum = file -> numberOfFunctions(); + + for (int i = 0; i < funcNum; ++i) { + SgStatement *st = file -> functions(i); + + vector blocks = findFuncBlocksByFuncStatement(st, FullIR); + map> loopsMapping = findAndAnalyzeLoops(st, blocks); + + for (auto& loopForAnalyze: loopsMapping) + processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR); + } + + //cout << "MOVE_OPERATORS Pass Completed" << endl; +} \ No newline at end of file diff --git a/src/Transformations/MoveOperators/move_operators.h b/src/Transformations/MoveOperators/move_operators.h new file mode 100644 index 0000000..0bbbc9a --- /dev/null +++ b/src/Transformations/MoveOperators/move_operators.h @@ -0,0 +1,6 @@ +#pragma once + +#include "../../GraphLoop/graph_loops.h" +#include "../../CFGraph/CFGraph.h" + +void moveOperators(SgFile *file, std::map>& loopGraph, const std::map>& FullIR, int& countOfTransform); diff --git a/src/Utils/PassManager.h b/src/Utils/PassManager.h index f2715d3..0ca232e 100644 --- a/src/Utils/PassManager.h +++ b/src/Utils/PassManager.h @@ -319,6 +319,8 @@ void InitPassesDependencies(map> &passDepsIn, set 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({ BUILD_IR, CALL_GRAPH2, RESTORE_LOOP_FROM_ASSIGN, REVERT_SUBST_EXPR_RD }) <= Pass(MOVE_OPERATORS); + 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, REVERSE_CREATED_NESTED_LOOPS, PREDICT_SCHEME, CALCULATE_STATS_SCHEME, REVERT_SPF_DIRS, CLEAR_SPF_DIRS, TRANSFORM_SHADOW_IF_FULL, diff --git a/src/Utils/version.h b/src/Utils/version.h index f6ac53b..ae0ca0d 100644 --- a/src/Utils/version.h +++ b/src/Utils/version.h @@ -1,3 +1,3 @@ #pragma once -#define VERSION_SPF "2450" +#define VERSION_SPF "2451" diff --git a/src/VisualizerCalls/get_information.cpp b/src/VisualizerCalls/get_information.cpp index 7bdd7c3..229d49b 100644 --- a/src/VisualizerCalls/get_information.cpp +++ b/src/VisualizerCalls/get_information.cpp @@ -1802,6 +1802,13 @@ int SPF_InsertPrivateArrayDirectives(void*& context, int winHandler, short* opti return simpleTransformPass(FIND_PRIVATE_ARRAYS, options, projName, folderName, output, outputMessage); } +int SPF_MoveOperators(void*& context, int winHandler, short* options, short* projName, short* folderName, string& output, string& outputMessage) +{ + MessageManager::clearCache(); + MessageManager::setWinHandler(winHandler); + return simpleTransformPass(MOVE_OPERATORS, options, projName, folderName, output, outputMessage); +} + static inline void convertBackSlash(char *str, int strL) { for (int z = 0; z < strL; ++z) @@ -2510,6 +2517,8 @@ const wstring Sapfor_RunTransformation(const char* transformName_c, const char* retCode = SPF_RenameIncludes(context, winHandler, optSh, projSh, fold, output, outputMessage); else if (whichRun == "SPF_InsertPrivateArrayDirectives") 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_CreateParallelVariant") { vector splited;