From 6907f44ac54a2d3f1009e2e5b856b09545991033 Mon Sep 17 00:00:00 2001 From: Egor Mayorov Date: Thu, 25 Dec 2025 15:01:01 +0300 Subject: [PATCH] fixes & improvements --- .../SwapOperators/swap_operators.cpp | 412 +++++++++++++++--- 1 file changed, 347 insertions(+), 65 deletions(-) diff --git a/src/Transformations/SwapOperators/swap_operators.cpp b/src/Transformations/SwapOperators/swap_operators.cpp index 3f5d28a..8871145 100644 --- a/src/Transformations/SwapOperators/swap_operators.cpp +++ b/src/Transformations/SwapOperators/swap_operators.cpp @@ -26,7 +26,6 @@ static vector findInstructionsFromOperator(SgStatement* st, v vector instructionsInBlock = block->getInstructions(); for (auto& instruction: instructionsInBlock) { SgStatement* curOperator = instruction->getInstruction()->getOperator(); - // Match by line number to find corresponding IR instruction if (curOperator->lineNumber() == st->lineNumber()) { result.push_back(instruction); } @@ -35,9 +34,9 @@ static vector findInstructionsFromOperator(SgStatement* st, v return result; } -unordered_set loop_tags = {FOR_NODE}; // Loop statements -unordered_set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; // Control structures that cannot be moved -unordered_set control_end_tags = {CONTROL_END}; // End marker +unordered_set loop_tags = {FOR_NODE}; +unordered_set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; +unordered_set control_end_tags = {CONTROL_END}; struct OperatorInfo { SgStatement* stmt; @@ -254,7 +253,7 @@ static int calculateDistance(SgStatement* from, SgStatement* to) { return abs(to->lineNumber() - from->lineNumber()); } -static SgStatement* findBestPosition(SgStatement* operatorStmt, vector& operators, map>& varDefinitions) { +static SgStatement* findBestPosition(SgStatement* operatorStmt, vector& operators, map>& varDefinitions, SgForStmt* loop) { OperatorInfo* opInfo = nullptr; for (auto& op : operators) { if (op.stmt == operatorStmt) { @@ -268,20 +267,52 @@ static SgStatement* findBestPosition(SgStatement* operatorStmt, vectorusedVars) { if (varDefinitions.find(usedVar) != varDefinitions.end()) { for (SgStatement* defStmt : varDefinitions[usedVar]) { - int distance = calculateDistance(operatorStmt, defStmt); - if (distance < minDistance) { - minDistance = distance; - bestPos = defStmt; + 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[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; } @@ -293,24 +324,37 @@ static bool canMoveTo(SgStatement* from, SgStatement* to, SgForStmt* loop) { 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; } - SgStatement* current = from; - unordered_set visited; + if (to->lineNumber() >= from->lineNumber()) { + return false; + } - while (current && current != loopEnd) { - - if (visited.find(current) != visited.end()) { - return false; - } - visited.insert(current); - + 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()) { - return false; + SgStatement* controlEnd = current->lastNodeOfStmt(); + if (controlEnd && from->lineNumber() <= controlEnd->lineNumber()) { + if (from->controlParent() == current && to->controlParent() != current) { + return false; + } + } } - if (current == to) break; current = current->lexNext(); } @@ -319,33 +363,204 @@ static bool canMoveTo(SgStatement* from, SgStatement* to, SgForStmt* loop) { static vector optimizeOperatorOrder(SgForStmt* loop, vector& operators, map>& varDefinitions) { vector newOrder; - vector moved(operators.size(), false); + for (auto& op : operators) { + newOrder.push_back(op.stmt); + } - for (size_t i = 0; i < operators.size(); i++) { - if (moved[i] || !operators[i].isMovable) { - newOrder.push_back(operators[i].stmt); - moved[i] = true; - continue; - } + map stmtToOpInfo; + for (auto& op : operators) { + stmtToOpInfo[op.stmt] = &op; + } + + bool changed = true; + int iterations = 0; + const int MAX_ITERATIONS = 50; + + while (changed && iterations < MAX_ITERATIONS) { + changed = false; + iterations++; - SgStatement* bestPos = findBestPosition(operators[i].stmt, operators, varDefinitions); - - if (bestPos && canMoveTo(operators[i].stmt, bestPos, loop)) { - bool inserted = false; + for (int i = operators.size() - 1; i >= 0; i--) { + if (!operators[i].isMovable) continue; + + SgStatement* stmt = operators[i].stmt; + OperatorInfo* opInfo = stmtToOpInfo[stmt]; + if (!opInfo) continue; + + size_t currentPos = 0; for (size_t j = 0; j < newOrder.size(); j++) { - if (newOrder[j] == bestPos) { - newOrder.insert(newOrder.begin() + j + 1, operators[i].stmt); - inserted = true; + if (newOrder[j] == stmt) { + currentPos = j; break; } } - if (!inserted) { - newOrder.push_back(operators[i].stmt); + + 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]; + 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]; + 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]; + 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]; + 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; + } + } } - } else { - newOrder.push_back(operators[i].stmt); } - moved[i] = 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]; + OperatorInfo* opInfo = stmtToOpInfo[stmt]; + if (!opInfo) continue; + + for (size_t j = 0; j < i; j++) { + SgStatement* prevStmt = newOrder[j]; + 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]; + 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; @@ -388,6 +603,7 @@ static bool applyOperatorReordering(SgForStmt* loop, vector& newOr vector savedComments; unordered_set extractedSet; map originalLineNumbers; + map stmtToExtracted; for (SgStatement* stmt : newOrder) { if (stmt && stmt != loop && stmt != loopEnd && extractedSet.find(stmt) == extractedSet.end()) { @@ -422,35 +638,77 @@ static bool applyOperatorReordering(SgForStmt* loop, vector& newOr if (extracted) { extractedStatements.push_back(extracted); extractedSet.insert(stmt); + stmtToExtracted[stmt] = extracted; } } } - SgStatement* currentPos = loop; + map insertedStatements; - for (size_t i = 0; i < extractedStatements.size(); i++) { - SgStatement* stmt = extractedStatements[i]; - if (stmt) { - SgStatement* nextPos = currentPos->lexNext(); - if (nextPos && nextPos != loopEnd) { - if (nextPos->variant() == FOR_NODE && nextPos != loop) { - continue; - } - if (nextPos->variant() == CONTROL_END) { - continue; + 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; } } - if (i < savedComments.size() && savedComments[i]) { - stmt->setComments(savedComments[i]); + 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()) { - stmt->setlineNumber(originalLineNumbers[stmt]); + stmtToInsert->setlineNumber(originalLineNumbers[stmt]); } - currentPos->insertStmtAfter(*stmt, *loop); - currentPos = stmt; + SgStatement* controlParent = stmt->controlParent(); + if (!controlParent) controlParent = loop; + + insertAfter->insertStmtAfter(*stmtToInsert, *controlParent); + insertedStatements[stmt] = stmtToInsert; } } @@ -460,10 +718,6 @@ static bool applyOperatorReordering(SgForStmt* loop, vector& newOr } } - if (currentPos && currentPos->lexNext() != loopEnd) { - currentPos->setLexNext(*loopEnd); - } - return true; } @@ -509,6 +763,37 @@ map> findAndAnalyzeLoops(SgStatement *st return result; } +static void processLoopRecursively(SgForStmt* loop, vector blocks, 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 runSwapOperators(SgFile *file, std::map>& loopGraph, std::map>& FullIR, int& countOfTransform) { countOfTransform += 1; @@ -524,10 +809,7 @@ void runSwapOperators(SgFile *file, std::map> loopsMapping = findAndAnalyzeLoops(st, blocks); for (pair> loopForAnalyze: loopsMapping) { - vector operators = analyzeOperatorsInLoop(loopForAnalyze.first, loopForAnalyze.second, FullIR); - map> varDefinitions = findVariableDefinitions(loopForAnalyze.first, operators); - vector newOrder = optimizeOperatorOrder(loopForAnalyze.first, operators, varDefinitions); - applyOperatorReordering(loopForAnalyze.first, newOrder); + processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR); } }