From 0b50e0630abe0f44aa03bad19f71f2dac1e0114b Mon Sep 17 00:00:00 2001 From: Egor Mayorov Date: Thu, 19 Feb 2026 09:21:10 +0300 Subject: [PATCH 1/5] use rd --- .../MoveOperators/move_operators.cpp | 1116 ++++++++--------- 1 file changed, 529 insertions(+), 587 deletions(-) diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index d310afe..6cf14d1 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -1,9 +1,12 @@ #include -#include +#include #include #include #include #include +#include +#include +#include #include "../../Utils/errors.h" #include "../../Utils/SgUtils.h" @@ -16,35 +19,130 @@ 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(); +string getNameByArg(SAPFOR::Argument* arg); - for (auto& instruction: instructionsInBlock) { - SgStatement* curOperator = instruction->getInstruction()->getOperator(); - if (curOperator->lineNumber() == st->lineNumber()) - result.push_back(instruction); +static vector findInstructionsFromStatement(SgStatement* st, const vector& blocks) +{ + vector result; + if (!st) + return result; + + const int stmtId = st->id(); + for (auto* bb : blocks) + { + if (!bb) + continue; + + for (auto* ir : bb->getInstructions()) + { + if (!ir || !ir->getInstruction()) + continue; + + SgStatement* op = ir->getInstruction()->getOperator(); + if (op && op->id() == stmtId) + result.push_back(ir); } } + + sort(result.begin(), result.end(), + [](const SAPFOR::IR_Block* a, const SAPFOR::IR_Block* b) { return a->getNumber() < b->getNumber(); }); 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 }; +set loop_tags = {FOR_NODE}; +set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; +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 isBarrierIR(const SAPFOR::Instruction* instr) +{ + if (!instr) + return true; + + using SAPFOR::CFG_OP; + const auto op = instr->getOperation(); + + switch (op) + { + case CFG_OP::F_CALL: + case CFG_OP::STORE: + case CFG_OP::REC_REF_STORE: + case CFG_OP::IO_PARAM: + case CFG_OP::DVM_DIR: + case CFG_OP::SPF_DIR: + case CFG_OP::POINTER_ASS: + case CFG_OP::EXIT: + return true; + default: + return false; + } +} + +static bool isMovableStmtIR(const vector& irs, + set& uses, + set& defs, + bool& spansMultipleBB) +{ + uses.clear(); + defs.clear(); + spansMultipleBB = false; + + if (irs.empty()) + return false; + + SAPFOR::BasicBlock* bb = irs.front()->getBasicBlock(); + for (auto* ir : irs) + if (ir && ir->getBasicBlock() != bb) + spansMultipleBB = true; + + for (auto* ir : irs) + { + if (!ir || !ir->getInstruction()) + return false; + + const auto* instr = ir->getInstruction(); + if (isBarrierIR(instr)) + return false; + + auto addUse = [&](SAPFOR::Argument* a) + { + if (!a) + return; + if (a->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + uses.insert(a); + else if (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD) + uses.insert(a); + }; + + auto addDef = [&](SAPFOR::Argument* a) + { + if (!a) + return; + if (a->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + defs.insert(a); + else if (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD) + defs.insert(a); + }; + + addUse(instr->getArg1()); + addUse(instr->getArg2()); + addDef(instr->getResult()); + } + + for (auto* a : uses) + if (a && (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD)) + return false; + for (auto* a : defs) + if (a && (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD)) + return false; + + if (spansMultipleBB) + return false; + + if (defs.empty()) + return false; + + return true; +} static bool isStatementEmbedded(SgStatement* stmt, SgStatement* parent) { if (!stmt || !parent || stmt == parent) @@ -154,575 +252,428 @@ static bool canSafelyExtract(SgStatement* stmt, SgForStmt* loop) { return true; } -static vector analyzeOperatorsInLoop(SgForStmt* loop, const vector& blocks, - const map>& FullIR) { - vector operators; +namespace +{ + struct StmtInfo + { + SgStatement* stmt = nullptr; + SAPFOR::BasicBlock* bb = nullptr; + int firstInstr = std::numeric_limits::max(); + int lastInstr = std::numeric_limits::min(); + vector irs; + set uses; + set defs; + }; + + using RDState = map>; + + static void killGlobalsAndParams(RDState& st) + { + for (auto it = st.begin(); it != st.end();) + { + SAPFOR::Argument* a = it->first; + if (!a) + { + it = st.erase(it); + continue; + } + + const bool kill = a->isMemGlobal() || a->isParameter(); + if (kill) + it = st.erase(it); + else + ++it; + } + } + + static void transferRD(RDState& st, const SAPFOR::Instruction* instr) + { + if (!instr) + return; + + if (isBarrierIR(instr)) + { + killGlobalsAndParams(st); + return; + } + + using SAPFOR::CFG_OP; + const auto op = instr->getOperation(); + if (op == CFG_OP::ASSIGN || op == CFG_OP::LOAD) + { + SAPFOR::Argument* res = instr->getResult(); + if (res && res->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + st[res] = { instr->getNumber() }; + } + } + + static RDState computeRD_BeforeInstr(const SAPFOR::BasicBlock* bb, int beforeInstrNum) + { + RDState st; + if (!bb) + return st; + + st = bb->getRD_In(); + for (auto* ir : bb->getInstructions()) + { + if (!ir || !ir->getInstruction()) + continue; + if (ir->getNumber() >= beforeInstrNum) + break; + transferRD(st, ir->getInstruction()); + } + return st; + } + + static bool topoSchedule(const vector& original, + const vector>& succ, + const vector& indegInit, + vector& scheduled) + { + const int n = (int)original.size(); + scheduled.clear(); + scheduled.reserve(n); + + vector indeg = indegInit; + vector maxPredPos(n, 0); + + struct Node + { + int idx; + int keyMaxPredPos; + }; + struct Cmp + { + bool operator()(const Node& a, const Node& b) const + { + if (a.keyMaxPredPos != b.keyMaxPredPos) + return a.keyMaxPredPos < b.keyMaxPredPos; + return a.idx > b.idx; + } + }; + + std::priority_queue, Cmp> ready; + for (int i = 0; i < n; ++i) + if (indeg[i] == 0) + ready.push(Node{ i, 0 }); + + int outPos = 0; + while (!ready.empty()) + { + Node cur = ready.top(); + ready.pop(); + + const int u = cur.idx; + scheduled.push_back(original[u]); + ++outPos; + + for (int v : succ[u]) + { + maxPredPos[v] = std::max(maxPredPos[v], outPos); + if (--indeg[v] == 0) + ready.push(Node{ v, maxPredPos[v] }); + } + } + + return (int)scheduled.size() == n; + } + + static bool applyReorderContiguous(SgForStmt* loop, + const vector& oldOrder, + const vector& newOrder) + { + if (!loop || oldOrder.size() != newOrder.size() || oldOrder.size() < 2) + return false; + + bool changed = false; + for (size_t i = 0; i < oldOrder.size(); ++i) + if (oldOrder[i] != newOrder[i]) + { + changed = true; + break; + } + if (!changed) + return false; + + SgStatement* loopStart = loop->lexNext(); + SgStatement* loopEnd = loop->lastNodeOfStmt(); + if (!loopStart || !loopEnd) + return false; + + SgStatement* first = oldOrder.front(); + SgStatement* anchor = loop; + for (SgStatement* cur = loopStart; cur && cur != loopEnd; cur = cur->lexNext()) + { + if (cur == first) + break; + anchor = cur; + } + + map savedLine; + map savedComments; + map extracted; + + for (SgStatement* st : oldOrder) + { + if (!st || st == loop || st == loopEnd) + return false; + if (!canSafelyExtract(st, loop)) + return false; + + savedLine[st] = st->lineNumber(); + savedComments[st] = st->comments() ? strdup(st->comments()) : nullptr; + + SgStatement* ex = st->extractStmt(); + if (!ex) + return false; + extracted[st] = ex; + } + + SgStatement* insertAfter = anchor; + for (SgStatement* st : newOrder) + { + SgStatement* ex = extracted[st]; + if (!ex) + continue; + + auto itC = savedComments.find(st); + if (itC != savedComments.end() && itC->second) + ex->setComments(itC->second); + + auto itL = savedLine.find(st); + if (itL != savedLine.end()) + ex->setlineNumber(itL->second); + + insertAfter->insertStmtAfter(*ex, *loop); + insertAfter = ex; + } + + for (auto& kv : savedComments) + if (kv.second) + free(kv.second); + + return true; + } +} + +static bool reorderMovableRegionsInLoop(SgForStmt* loop, const vector& blocks) +{ + if (!loop) + return false; + SgStatement* loopStart = loop->lexNext(); SgStatement* loopEnd = loop->lastNodeOfStmt(); - if (!loopStart || !loopEnd) - return operators; - + return false; + + bool anyChange = false; + + vector region; + auto flushRegion = [&]() { + if (region.size() < 2) + { + region.clear(); + return; + } + + vector infos; + infos.reserve(region.size()); + map idxOf; + + map defInstrToIdx; + + for (int i = 0; i < (int)region.size(); ++i) + { + SgStatement* st = region[i]; + idxOf[st] = i; + + StmtInfo info; + info.stmt = st; + info.irs = findInstructionsFromStatement(st, blocks); + if (info.irs.empty()) + { + infos.clear(); + region.clear(); + return; + } + + info.bb = info.irs.front()->getBasicBlock(); + for (auto* ir : info.irs) + { + info.firstInstr = std::min(info.firstInstr, ir->getNumber()); + info.lastInstr = std::max(info.lastInstr, ir->getNumber()); + + const auto* instr = ir->getInstruction(); + if (!instr) + continue; + + if (instr->getResult() && instr->getResult()->getType() == SAPFOR::CFG_ARG_TYPE::VAR && + (instr->getOperation() == SAPFOR::CFG_OP::ASSIGN || instr->getOperation() == SAPFOR::CFG_OP::LOAD)) + { + defInstrToIdx[instr->getNumber()] = i; + } + } + + bool spansMultiple = false; + if (!isMovableStmtIR(info.irs, info.uses, info.defs, spansMultiple) || spansMultiple) + { + infos.clear(); + region.clear(); + return; + } + + infos.push_back(std::move(info)); + } + + const int n = (int)infos.size(); + vector> succ(n); + vector indeg(n, 0); + + auto addEdge = [&](int u, int v) { + if (u == v) + return; + succ[u].push_back(v); + indeg[v]++; + }; + + for (int i = 0; i < n; ++i) + { + const StmtInfo& cur = infos[i]; + RDState stRD = computeRD_BeforeInstr(cur.bb, cur.firstInstr); + + for (SAPFOR::Argument* use : cur.uses) + { + if (!use || use->getType() != SAPFOR::CFG_ARG_TYPE::VAR) + continue; + + auto it = stRD.find(use); + if (it == stRD.end()) + continue; + + for (int defInstr : it->second) + { + if (defInstr < 0) + continue; + + auto itDef = defInstrToIdx.find(defInstr); + if (itDef != defInstrToIdx.end()) + addEdge(itDef->second, i); + } + } + } + + map> defsByVar; + for (int i = 0; i < n; ++i) + for (auto* d : infos[i].defs) + if (d && d->getType() == SAPFOR::CFG_ARG_TYPE::VAR) + defsByVar[d].push_back(i); + + for (auto& kv : defsByVar) + { + auto& list = kv.second; + sort(list.begin(), list.end()); + list.erase(unique(list.begin(), list.end()), list.end()); + for (int k = 0; k + 1 < (int)list.size(); ++k) + addEdge(list[k], list[k + 1]); + } + + map> defPositions; + for (auto& kv : defsByVar) + defPositions[kv.first] = kv.second; + + for (int i = 0; i < n; ++i) + { + for (SAPFOR::Argument* use : infos[i].uses) + { + if (!use || use->getType() != SAPFOR::CFG_ARG_TYPE::VAR) + continue; + + auto itDefs = defPositions.find(use); + if (itDefs == defPositions.end()) + continue; + + const auto& dpos = itDefs->second; + auto it = std::upper_bound(dpos.begin(), dpos.end(), i); + if (it != dpos.end()) + addEdge(i, *it); + } + } + + for (int u = 0; u < n; ++u) + { + auto& out = succ[u]; + sort(out.begin(), out.end()); + out.erase(unique(out.begin(), out.end()), out.end()); + } + fill(indeg.begin(), indeg.end(), 0); + for (int u = 0; u < n; ++u) + for (int v : succ[u]) + indeg[v]++; + + vector scheduled; + vector original = region; + if (!topoSchedule(original, succ, indeg, scheduled)) + { + region.clear(); + return; + } + + if (applyReorderContiguous(loop, original, scheduled)) + anyChange = true; + + region.clear(); + }; + SgStatement* current = loopStart; - unordered_set visited; - - while (current && current != loopEnd) { - - if (visited.find(current) != visited.end()) + set visited; + + while (current && current != loopEnd) + { + if (!visited.insert(current).second) break; - visited.insert(current); - - if (isLoopBoundary(current)) { + if (isLoopBoundary(current)) + { + flushRegion(); current = current->lexNext(); continue; } - - if (current->variant() == FOR_NODE && current != loop) { + + if (current->variant() == FOR_NODE && current != loop) + { + flushRegion(); SgStatement* nestedEnd = current->lastNodeOfStmt(); - if (nestedEnd) - current = nestedEnd->lexNext(); - else - current = current->lexNext(); + current = nestedEnd ? nestedEnd->lexNext() : current->lexNext(); continue; } - - if (isSgExecutableStatement(current)) { - if (control_tags.find(current->variant()) != control_tags.end()) { + + if (!isSgExecutableStatement(current) || control_tags.count(current->variant())) + { + flushRegion(); + current = current->lexNext(); + continue; + } + + const bool isTopLevel = (current->controlParent() == loop); + if (isTopLevel && current->variant() == ASSIGN_STAT && canSafelyExtract(current, loop)) + { + auto irs = findInstructionsFromStatement(current, blocks); + set uses, defs; + bool spansMultiple = false; + if (isMovableStmtIR(irs, uses, defs, spansMultiple) && !spansMultiple) + { + region.push_back(current); 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); } + + flushRegion(); 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; + flushRegion(); + return anyChange; } vector findFuncBlocksByFuncStatement(SgStatement *st, const map>& FullIR) { @@ -748,10 +699,10 @@ map> findAndAnalyzeLoops(SgStatement *st SgForStmt *forSt = (SgForStmt*)st; SgStatement *loopBody = forSt -> body(); SgStatement *lastLoopNode = st->lastNodeOfStmt(); - unordered_set blocks_nums; + set blocks_nums; while (loopBody && loopBody != lastLoopNode) { - vector irBlocks = findInstructionsFromOperator(loopBody, blocks); + vector irBlocks = findInstructionsFromStatement(loopBody, blocks); if (!irBlocks.empty()) { SAPFOR::IR_Block* IR = irBlocks.front(); if (IR && IR->getBasicBlock()) { @@ -794,24 +745,17 @@ static void processLoopRecursively(SgForStmt* loop, const vectorlexNext(); } } - - vector operators = analyzeOperatorsInLoop(loop, blocks, FullIR); - if (!operators.empty()) { - map> varDefinitions = findVariableDefinitions(loop, operators); - vector newOrder = optimizeOperatorOrder(loop, operators, varDefinitions); - applyOperatorReordering(loop, newOrder); - } + + reorderMovableRegionsInLoop(loop, blocks); } 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); @@ -821,6 +765,4 @@ void moveOperators(SgFile *file, map>& loopGraph, for (auto& loopForAnalyze: loopsMapping) processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR); } - - //cout << "MOVE_OPERATORS Pass Completed" << endl; } \ No newline at end of file From 0a977146a7833ccbee66ab33650c3cd755926eed Mon Sep 17 00:00:00 2001 From: Egor Mayorov Date: Thu, 26 Feb 2026 00:57:50 +0300 Subject: [PATCH 2/5] Analyze program block by block & reorder operators only in basic blocks --- .../MoveOperators/move_operators.cpp | 393 +++++++++++++++++- 1 file changed, 384 insertions(+), 9 deletions(-) diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index 6cf14d1..60d36f8 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -749,20 +749,395 @@ static void processLoopRecursively(SgForStmt* loop, const vector findBlocksInLoopsByFullIR( + SgStatement* funcStmt, + const map>& FullIR) +{ + vector result; + if (!funcStmt) + return result; + + const vector funcBlocks = findFuncBlocksByFuncStatement(funcStmt, FullIR); + const auto loopsMapping = findAndAnalyzeLoops(funcStmt, funcBlocks); + + set uniq; + for (const auto& kv : loopsMapping) + for (auto* bb : kv.second) + if (bb) + uniq.insert(bb); + + result.assign(uniq.begin(), uniq.end()); + sort(result.begin(), result.end(), + [](const SAPFOR::BasicBlock* a, const SAPFOR::BasicBlock* b) + { + if (!a || !b) + return a < b; + return a->getNumber() < b->getNumber(); + }); + + return result; +} + +static map> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb) +{ + map> result; + if (!bb) + return result; + + auto isCompoundStmt = [](SgStatement* st) -> bool + { + if (!st) + return true; + const int v = st->variant(); + return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v); + }; + + auto isTrackable = [](const SAPFOR::Argument* a) -> bool + { + if (!a) + return false; + const auto t = a->getType(); + return t == SAPFOR::CFG_ARG_TYPE::VAR || t == SAPFOR::CFG_ARG_TYPE::REG; + }; + + auto argKey = [&](const SAPFOR::Argument* a) -> string + { + if (!a) + return string(); + return to_string((int)a->getType()) + "#" + to_string((int)a->getMemType()) + "#" + a->getValue(); + }; + + auto isBarrier = [&](const SAPFOR::Instruction* instr) -> bool + { + if (!instr) + return true; + const auto op = instr->getOperation(); + switch (op) + { + case SAPFOR::CFG_OP::F_CALL: + case SAPFOR::CFG_OP::STORE: + case SAPFOR::CFG_OP::REC_REF_STORE: + case SAPFOR::CFG_OP::IO_PARAM: + case SAPFOR::CFG_OP::DVM_DIR: + case SAPFOR::CFG_OP::SPF_DIR: + case SAPFOR::CFG_OP::POINTER_ASS: + case SAPFOR::CFG_OP::EXIT: + return true; + default: + return false; + } + }; + + auto isDef = [&](const SAPFOR::Instruction* instr) -> bool + { + if (!instr) + return false; + SAPFOR::Argument* r = instr->getResult(); + if (!isTrackable(r)) + return false; + + const auto op = instr->getOperation(); + if (op == SAPFOR::CFG_OP::STORE || op == SAPFOR::CFG_OP::REC_REF_STORE) + return false; + + return true; + }; + + // Reaching definitions inside the BasicBlock in straight-line order: + // lastDef[var] = last operator in this block that defined it. + map> lastDef; + map> depsSets; + + for (auto* ir : bb->getInstructions()) + { + if (!ir || !ir->getInstruction()) + continue; + + const SAPFOR::Instruction* instr = ir->getInstruction(); + SgStatement* opStmt = instr->getOperator(); + if (!opStmt || isCompoundStmt(opStmt)) + continue; + + if (isBarrier(instr)) + { + for (auto it = lastDef.begin(); it != lastDef.end();) + { + const SAPFOR::Argument* a = it->second.second; + if (!a || a->isMemGlobal() || a->isParameter()) + it = lastDef.erase(it); + else + ++it; + } + } + + if (!result.count(opStmt)) + result[opStmt] = {}; + + auto addDep = [&](SAPFOR::Argument* use) + { + if (!isTrackable(use)) + return; + auto it = lastDef.find(argKey(use)); + if (it == lastDef.end()) + return; // only deps inside this BB are needed + if (it->second.first && it->second.first != opStmt) + depsSets[opStmt].insert(it->second.first); + }; + + addDep(instr->getArg1()); + addDep(instr->getArg2()); + + if (isDef(instr)) + lastDef[argKey(instr->getResult())] = { opStmt, instr->getResult() }; + } + + for (auto& kv : result) + { + SgStatement* op = kv.first; + auto it = depsSets.find(op); + if (it == depsSets.end()) + continue; + + kv.second.assign(it->second.begin(), it->second.end()); + sort(kv.second.begin(), kv.second.end(), + [](SgStatement* a, SgStatement* b) + { + const int la = a ? a->lineNumber() : -1; + const int lb = b ? b->lineNumber() : -1; + if (la != lb) + return la < lb; + return a < b; + }); + } + + return result; +} + +static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb) +{ + if (!bb) + return false; + + auto isCompoundStmt = [](SgStatement* st) -> bool + { + if (!st) + return true; + const int v = st->variant(); + return loop_tags.count(v) || control_tags.count(v) || control_end_tags.count(v); + }; + + vector ops; + ops.reserve(bb->getInstructions().size()); + set seen; + for (auto* ir : bb->getInstructions()) + { + if (!ir || !ir->getInstruction()) + continue; + SgStatement* st = ir->getInstruction()->getOperator(); + if (!st || isCompoundStmt(st)) + continue; + if (seen.insert(st).second) + ops.push_back(st); + } + + if (ops.size() < 2) + return false; + + SgStatement* parent = ops.front()->controlParent(); + if (!parent) + return false; + for (auto* st : ops) + if (!st || st->controlParent() != parent) + return false; + + set opSet(ops.begin(), ops.end()); + { + SgStatement* lastNode = parent->lastNodeOfStmt(); + SgStatement* cur = ops.front(); + size_t idx = 0; + + { + SgStatement* scan = parent->lexNext(); + SgStatement* end = lastNode; + bool found = false; + while (scan && scan != end) + { + if (scan == ops.front()) + { + found = true; + break; + } + scan = scan->lexNext(); + } + if (!found) + return false; + } + + while (cur && cur != lastNode && idx < ops.size()) + { + if (cur == ops[idx]) + { + ++idx; + } + else + { + if (isSgExecutableStatement(cur) && !opSet.count(cur)) + return false; + } + if (idx == ops.size()) + break; + cur = cur->lexNext(); + } + if (idx != ops.size()) + return false; + } + + // Compute dependencies (inside BB) and build a new order by moving each statement + // as close as possible after its last dependency (if any). + const auto depsMap = analyzeBasicBlockIntraDependencies(bb); + vector order = ops; + + map pos; + for (int i = 0; i < (int)order.size(); ++i) + pos[order[i]] = i; + + for (int i = 0; i < (int)order.size(); ++i) + { + SgStatement* cur = order[i]; + auto it = depsMap.find(cur); + if (it == depsMap.end() || it->second.empty()) + continue; + + int lastDepIdx = -1; + for (SgStatement* dep : it->second) + { + auto itP = pos.find(dep); + if (itP != pos.end()) + lastDepIdx = max(lastDepIdx, itP->second); + } + + if (lastDepIdx < 0) + continue; + + const int target = lastDepIdx + 1; + if (target == i) + continue; + + SgStatement* moved = order[i]; + order.erase(order.begin() + i); + + int insertIdx = target; + if (target > i) + insertIdx = target - 1; + if (insertIdx < 0) + insertIdx = 0; + if (insertIdx > (int)order.size()) + insertIdx = (int)order.size(); + + order.insert(order.begin() + insertIdx, moved); + + pos.clear(); + for (int k = 0; k < (int)order.size(); ++k) + pos[order[k]] = k; + + i = max(-1, min(i, insertIdx) - 1); + } + + bool changed = false; + for (size_t i = 0; i < ops.size(); ++i) + if (ops[i] != order[i]) + { + changed = true; + break; + } + if (!changed) + return false; + + SgStatement* anchor = parent; + { + SgStatement* scan = parent->lexNext(); + SgStatement* end = parent->lastNodeOfStmt(); + while (scan && scan != end) + { + if (scan == ops.front()) + break; + anchor = scan; + scan = scan->lexNext(); + } + } + + // apply AST reordering + map savedLine; + map savedComments; + map extracted; + + for (SgStatement* st : ops) + { + if (!st) + return false; + + savedLine[st] = st->lineNumber(); + savedComments[st] = st->comments() ? strdup(st->comments()) : nullptr; + + SgStatement* ex = st->extractStmt(); + if (!ex) + return false; + extracted[st] = ex; + } + + SgStatement* insertAfter = anchor; + for (SgStatement* st : order) + { + SgStatement* ex = extracted[st]; + if (!ex) + continue; + + auto itC = savedComments.find(st); + if (itC != savedComments.end() && itC->second) + ex->setComments(itC->second); + + auto itL = savedLine.find(st); + if (itL != savedLine.end()) + ex->setlineNumber(itL->second); + + insertAfter->insertStmtAfter(*ex, *parent); + insertAfter = ex; + } + + for (auto& kv : savedComments) + if (kv.second) + free(kv.second); + + return true; +} + void moveOperators(SgFile *file, map>& loopGraph, const map>& FullIR, int& countOfTransform) { - countOfTransform += 1; + // countOfTransform += 1; - const int funcNum = file -> numberOfFunctions(); + if (!file) + return; + + 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); + SgStatement* st = file->functions(i); + + const auto loopBlocks = findBlocksInLoopsByFullIR(st, FullIR); + for (auto* bb : loopBlocks) + { + if (!bb) + continue; + if (reorderOperatorsInBasicBlockUsingDeps(bb)) + countOfTransform += 1; + } + + // vector blocks = findFuncBlocksByFuncStatement(st, FullIR); + // map> loopsMapping = findAndAnalyzeLoops(st, blocks); + + // for (auto& loopForAnalyze : loopsMapping) + // processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR); } } \ No newline at end of file From e172678e1b4752a478c2227750f69a9d2310d45c Mon Sep 17 00:00:00 2001 From: Egor Mayorov Date: Sun, 8 Mar 2026 18:28:21 +0300 Subject: [PATCH 3/5] fix freezing --- .../MoveOperators/move_operators.cpp | 193 +++++++++++++----- 1 file changed, 141 insertions(+), 52 deletions(-) diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index 60d36f8..f7c197e 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -808,6 +808,47 @@ static map> analyzeBasicBlockIntraDependencie return to_string((int)a->getType()) + "#" + to_string((int)a->getMemType()) + "#" + a->getValue(); }; + auto memKeyFromInstr = [&](const SAPFOR::Instruction* instr) -> string + { + if (!instr) + return string(); + SgExpression* ex = instr->getExpression(); + if (!ex || !ex->unparse()) + return string(); + auto normalizeExprText = [](const string& raw) -> string + { + string t; + t.reserve(raw.size()); + for (unsigned char c : raw) + if (!std::isspace(c)) + t.push_back((char)c); + + auto stripOneLayer = [](const string& x) -> string + { + if (x.size() < 2 || x.front() != '(' || x.back() != ')') + return x; + int bal = 0; + for (size_t i = 0; i + 1 < x.size(); ++i) + { + if (x[i] == '(') bal++; + else if (x[i] == ')') bal--; + if (bal == 0 && i + 1 < x.size() - 1) + return x; + } + return x.substr(1, x.size() - 2); + }; + while (true) + { + const string stripped = stripOneLayer(t); + if (stripped == t) + break; + t = stripped; + } + return t; + }; + return "MEMEX#" + normalizeExprText(ex->unparse()); + }; + auto isBarrier = [&](const SAPFOR::Instruction* instr) -> bool { if (!instr) @@ -816,8 +857,6 @@ static map> analyzeBasicBlockIntraDependencie switch (op) { case SAPFOR::CFG_OP::F_CALL: - case SAPFOR::CFG_OP::STORE: - case SAPFOR::CFG_OP::REC_REF_STORE: case SAPFOR::CFG_OP::IO_PARAM: case SAPFOR::CFG_OP::DVM_DIR: case SAPFOR::CFG_OP::SPF_DIR: @@ -847,6 +886,7 @@ static map> analyzeBasicBlockIntraDependencie // Reaching definitions inside the BasicBlock in straight-line order: // lastDef[var] = last operator in this block that defined it. map> lastDef; + map> lastMemDef; map> depsSets; for (auto* ir : bb->getInstructions()) @@ -856,7 +896,9 @@ static map> analyzeBasicBlockIntraDependencie const SAPFOR::Instruction* instr = ir->getInstruction(); SgStatement* opStmt = instr->getOperator(); - if (!opStmt || isCompoundStmt(opStmt)) + if (!opStmt) + continue; + if (isCompoundStmt(opStmt)) continue; if (isBarrier(instr)) @@ -869,6 +911,14 @@ static map> analyzeBasicBlockIntraDependencie else ++it; } + for (auto it = lastMemDef.begin(); it != lastMemDef.end();) + { + const SAPFOR::Argument* a = it->second.second; + if (!a || a->isMemGlobal() || a->isParameter()) + it = lastMemDef.erase(it); + else + ++it; + } } if (!result.count(opStmt)) @@ -878,18 +928,50 @@ static map> analyzeBasicBlockIntraDependencie { if (!isTrackable(use)) return; - auto it = lastDef.find(argKey(use)); + const string k = argKey(use); + auto it = lastDef.find(k); if (it == lastDef.end()) - return; // only deps inside this BB are needed + return; + if (it->second.first && it->second.first != opStmt) + depsSets[opStmt].insert(it->second.first); + }; + + auto addMemDep = [&](const string& key) + { + if (key.empty()) + return; + auto it = lastMemDef.find(key); + if (it == lastMemDef.end()) + return; if (it->second.first && it->second.first != opStmt) depsSets[opStmt].insert(it->second.first); }; addDep(instr->getArg1()); addDep(instr->getArg2()); + if (instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) + addDep(instr->getResult()); + + if (instr->getOperation() == SAPFOR::CFG_OP::LOAD || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_LOAD) + { + const string memKey = memKeyFromInstr(instr); + addMemDep(memKey); + } if (isDef(instr)) - lastDef[argKey(instr->getResult())] = { opStmt, instr->getResult() }; + { + const string dk = argKey(instr->getResult()); + lastDef[dk] = { opStmt, instr->getResult() }; + } + + if (instr->getOperation() == SAPFOR::CFG_OP::STORE || instr->getOperation() == SAPFOR::CFG_OP::REC_REF_STORE) + { + const string k = memKeyFromInstr(instr); + SAPFOR::Argument* base = instr->getArg1(); + if (!k.empty() && base) + lastMemDef[k] = { opStmt, base }; + addMemDep(k); + } } for (auto& kv : result) @@ -961,8 +1043,11 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb) SgStatement* scan = parent->lexNext(); SgStatement* end = lastNode; bool found = false; + set visited; while (scan && scan != end) { + if (!visited.insert(scan).second) + return false; if (scan == ops.front()) { found = true; @@ -977,14 +1062,9 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb) while (cur && cur != lastNode && idx < ops.size()) { if (cur == ops[idx]) - { ++idx; - } - else - { - if (isSgExecutableStatement(cur) && !opSet.count(cur)) - return false; - } + else if (isSgExecutableStatement(cur) && !opSet.count(cur)) + return false; if (idx == ops.size()) break; cur = cur->lexNext(); @@ -998,50 +1078,59 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb) const auto depsMap = analyzeBasicBlockIntraDependencies(bb); vector order = ops; - map pos; - for (int i = 0; i < (int)order.size(); ++i) - pos[order[i]] = i; - - for (int i = 0; i < (int)order.size(); ++i) + auto buildPos = [&](const vector& v) { - SgStatement* cur = order[i]; - auto it = depsMap.find(cur); - if (it == depsMap.end() || it->second.empty()) - continue; + map pos; + for (int i = 0; i < (int)v.size(); ++i) + pos[v[i]] = i; + return pos; + }; - int lastDepIdx = -1; - for (SgStatement* dep : it->second) + const int maxIterations = (int)order.size() * (int)order.size() + 10; + bool anyMove = false; + for (int iter = 0; iter < maxIterations; ++iter) + { + bool movedThisIter = false; + const auto pos = buildPos(order); + + for (int i = 0; i < (int)order.size(); ++i) { - auto itP = pos.find(dep); - if (itP != pos.end()) - lastDepIdx = max(lastDepIdx, itP->second); + SgStatement* curSt = order[i]; + auto it = depsMap.find(curSt); + if (it == depsMap.end() || it->second.empty()) + continue; + + int lastDepIdx = -1; + for (SgStatement* dep : it->second) + { + auto itP = pos.find(dep); + if (itP != pos.end()) + lastDepIdx = max(lastDepIdx, itP->second); + } + if (lastDepIdx < 0) + continue; + + int target = lastDepIdx + 1; + if (target == i) + continue; + + SgStatement* moved = order[i]; + order.erase(order.begin() + i); + if (target > i) + target -= 1; + if (target < 0) + target = 0; + if (target > (int)order.size()) + target = (int)order.size(); + order.insert(order.begin() + target, moved); + + movedThisIter = true; + anyMove = true; + break; } - if (lastDepIdx < 0) - continue; - - const int target = lastDepIdx + 1; - if (target == i) - continue; - - SgStatement* moved = order[i]; - order.erase(order.begin() + i); - - int insertIdx = target; - if (target > i) - insertIdx = target - 1; - if (insertIdx < 0) - insertIdx = 0; - if (insertIdx > (int)order.size()) - insertIdx = (int)order.size(); - - order.insert(order.begin() + insertIdx, moved); - - pos.clear(); - for (int k = 0; k < (int)order.size(); ++k) - pos[order[k]] = k; - - i = max(-1, min(i, insertIdx) - 1); + if (!movedThisIter) + break; } bool changed = false; From 4818884d48d8d2c7d63c5f1ccf4c6e8e7c7836f5 Mon Sep 17 00:00:00 2001 From: Egor Mayorov Date: Sun, 8 Mar 2026 18:34:00 +0300 Subject: [PATCH 4/5] Remove redundant functions --- .../MoveOperators/move_operators.cpp | 671 +----------------- 1 file changed, 5 insertions(+), 666 deletions(-) diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index f7c197e..1096b0b 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -1,10 +1,8 @@ #include #include #include -#include #include #include -#include #include #include @@ -19,7 +17,11 @@ using namespace std; -string getNameByArg(SAPFOR::Argument* arg); + +set loop_tags = {FOR_NODE}; +set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; +set control_end_tags = {CONTROL_END}; + static vector findInstructionsFromStatement(SgStatement* st, const vector& blocks) { @@ -49,633 +51,6 @@ static vector findInstructionsFromStatement(SgStatement* st, return result; } -set loop_tags = {FOR_NODE}; -set control_tags = {IF_NODE, ELSEIF_NODE, DO_WHILE_NODE, WHILE_NODE, LOGIF_NODE}; -set control_end_tags = {CONTROL_END}; - -static bool isBarrierIR(const SAPFOR::Instruction* instr) -{ - if (!instr) - return true; - - using SAPFOR::CFG_OP; - const auto op = instr->getOperation(); - - switch (op) - { - case CFG_OP::F_CALL: - case CFG_OP::STORE: - case CFG_OP::REC_REF_STORE: - case CFG_OP::IO_PARAM: - case CFG_OP::DVM_DIR: - case CFG_OP::SPF_DIR: - case CFG_OP::POINTER_ASS: - case CFG_OP::EXIT: - return true; - default: - return false; - } -} - -static bool isMovableStmtIR(const vector& irs, - set& uses, - set& defs, - bool& spansMultipleBB) -{ - uses.clear(); - defs.clear(); - spansMultipleBB = false; - - if (irs.empty()) - return false; - - SAPFOR::BasicBlock* bb = irs.front()->getBasicBlock(); - for (auto* ir : irs) - if (ir && ir->getBasicBlock() != bb) - spansMultipleBB = true; - - for (auto* ir : irs) - { - if (!ir || !ir->getInstruction()) - return false; - - const auto* instr = ir->getInstruction(); - if (isBarrierIR(instr)) - return false; - - auto addUse = [&](SAPFOR::Argument* a) - { - if (!a) - return; - if (a->getType() == SAPFOR::CFG_ARG_TYPE::VAR) - uses.insert(a); - else if (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD) - uses.insert(a); - }; - - auto addDef = [&](SAPFOR::Argument* a) - { - if (!a) - return; - if (a->getType() == SAPFOR::CFG_ARG_TYPE::VAR) - defs.insert(a); - else if (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD) - defs.insert(a); - }; - - addUse(instr->getArg1()); - addUse(instr->getArg2()); - addDef(instr->getResult()); - } - - for (auto* a : uses) - if (a && (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD)) - return false; - for (auto* a : defs) - if (a && (a->getType() == SAPFOR::CFG_ARG_TYPE::ARRAY || a->getType() == SAPFOR::CFG_ARG_TYPE::RECORD)) - return false; - - if (spansMultipleBB) - return false; - - if (defs.empty()) - return false; - - return 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; -} - -namespace -{ - struct StmtInfo - { - SgStatement* stmt = nullptr; - SAPFOR::BasicBlock* bb = nullptr; - int firstInstr = std::numeric_limits::max(); - int lastInstr = std::numeric_limits::min(); - vector irs; - set uses; - set defs; - }; - - using RDState = map>; - - static void killGlobalsAndParams(RDState& st) - { - for (auto it = st.begin(); it != st.end();) - { - SAPFOR::Argument* a = it->first; - if (!a) - { - it = st.erase(it); - continue; - } - - const bool kill = a->isMemGlobal() || a->isParameter(); - if (kill) - it = st.erase(it); - else - ++it; - } - } - - static void transferRD(RDState& st, const SAPFOR::Instruction* instr) - { - if (!instr) - return; - - if (isBarrierIR(instr)) - { - killGlobalsAndParams(st); - return; - } - - using SAPFOR::CFG_OP; - const auto op = instr->getOperation(); - if (op == CFG_OP::ASSIGN || op == CFG_OP::LOAD) - { - SAPFOR::Argument* res = instr->getResult(); - if (res && res->getType() == SAPFOR::CFG_ARG_TYPE::VAR) - st[res] = { instr->getNumber() }; - } - } - - static RDState computeRD_BeforeInstr(const SAPFOR::BasicBlock* bb, int beforeInstrNum) - { - RDState st; - if (!bb) - return st; - - st = bb->getRD_In(); - for (auto* ir : bb->getInstructions()) - { - if (!ir || !ir->getInstruction()) - continue; - if (ir->getNumber() >= beforeInstrNum) - break; - transferRD(st, ir->getInstruction()); - } - return st; - } - - static bool topoSchedule(const vector& original, - const vector>& succ, - const vector& indegInit, - vector& scheduled) - { - const int n = (int)original.size(); - scheduled.clear(); - scheduled.reserve(n); - - vector indeg = indegInit; - vector maxPredPos(n, 0); - - struct Node - { - int idx; - int keyMaxPredPos; - }; - struct Cmp - { - bool operator()(const Node& a, const Node& b) const - { - if (a.keyMaxPredPos != b.keyMaxPredPos) - return a.keyMaxPredPos < b.keyMaxPredPos; - return a.idx > b.idx; - } - }; - - std::priority_queue, Cmp> ready; - for (int i = 0; i < n; ++i) - if (indeg[i] == 0) - ready.push(Node{ i, 0 }); - - int outPos = 0; - while (!ready.empty()) - { - Node cur = ready.top(); - ready.pop(); - - const int u = cur.idx; - scheduled.push_back(original[u]); - ++outPos; - - for (int v : succ[u]) - { - maxPredPos[v] = std::max(maxPredPos[v], outPos); - if (--indeg[v] == 0) - ready.push(Node{ v, maxPredPos[v] }); - } - } - - return (int)scheduled.size() == n; - } - - static bool applyReorderContiguous(SgForStmt* loop, - const vector& oldOrder, - const vector& newOrder) - { - if (!loop || oldOrder.size() != newOrder.size() || oldOrder.size() < 2) - return false; - - bool changed = false; - for (size_t i = 0; i < oldOrder.size(); ++i) - if (oldOrder[i] != newOrder[i]) - { - changed = true; - break; - } - if (!changed) - return false; - - SgStatement* loopStart = loop->lexNext(); - SgStatement* loopEnd = loop->lastNodeOfStmt(); - if (!loopStart || !loopEnd) - return false; - - SgStatement* first = oldOrder.front(); - SgStatement* anchor = loop; - for (SgStatement* cur = loopStart; cur && cur != loopEnd; cur = cur->lexNext()) - { - if (cur == first) - break; - anchor = cur; - } - - map savedLine; - map savedComments; - map extracted; - - for (SgStatement* st : oldOrder) - { - if (!st || st == loop || st == loopEnd) - return false; - if (!canSafelyExtract(st, loop)) - return false; - - savedLine[st] = st->lineNumber(); - savedComments[st] = st->comments() ? strdup(st->comments()) : nullptr; - - SgStatement* ex = st->extractStmt(); - if (!ex) - return false; - extracted[st] = ex; - } - - SgStatement* insertAfter = anchor; - for (SgStatement* st : newOrder) - { - SgStatement* ex = extracted[st]; - if (!ex) - continue; - - auto itC = savedComments.find(st); - if (itC != savedComments.end() && itC->second) - ex->setComments(itC->second); - - auto itL = savedLine.find(st); - if (itL != savedLine.end()) - ex->setlineNumber(itL->second); - - insertAfter->insertStmtAfter(*ex, *loop); - insertAfter = ex; - } - - for (auto& kv : savedComments) - if (kv.second) - free(kv.second); - - return true; - } -} - -static bool reorderMovableRegionsInLoop(SgForStmt* loop, const vector& blocks) -{ - if (!loop) - return false; - - SgStatement* loopStart = loop->lexNext(); - SgStatement* loopEnd = loop->lastNodeOfStmt(); - if (!loopStart || !loopEnd) - return false; - - bool anyChange = false; - - vector region; - auto flushRegion = [&]() { - if (region.size() < 2) - { - region.clear(); - return; - } - - vector infos; - infos.reserve(region.size()); - map idxOf; - - map defInstrToIdx; - - for (int i = 0; i < (int)region.size(); ++i) - { - SgStatement* st = region[i]; - idxOf[st] = i; - - StmtInfo info; - info.stmt = st; - info.irs = findInstructionsFromStatement(st, blocks); - if (info.irs.empty()) - { - infos.clear(); - region.clear(); - return; - } - - info.bb = info.irs.front()->getBasicBlock(); - for (auto* ir : info.irs) - { - info.firstInstr = std::min(info.firstInstr, ir->getNumber()); - info.lastInstr = std::max(info.lastInstr, ir->getNumber()); - - const auto* instr = ir->getInstruction(); - if (!instr) - continue; - - if (instr->getResult() && instr->getResult()->getType() == SAPFOR::CFG_ARG_TYPE::VAR && - (instr->getOperation() == SAPFOR::CFG_OP::ASSIGN || instr->getOperation() == SAPFOR::CFG_OP::LOAD)) - { - defInstrToIdx[instr->getNumber()] = i; - } - } - - bool spansMultiple = false; - if (!isMovableStmtIR(info.irs, info.uses, info.defs, spansMultiple) || spansMultiple) - { - infos.clear(); - region.clear(); - return; - } - - infos.push_back(std::move(info)); - } - - const int n = (int)infos.size(); - vector> succ(n); - vector indeg(n, 0); - - auto addEdge = [&](int u, int v) { - if (u == v) - return; - succ[u].push_back(v); - indeg[v]++; - }; - - for (int i = 0; i < n; ++i) - { - const StmtInfo& cur = infos[i]; - RDState stRD = computeRD_BeforeInstr(cur.bb, cur.firstInstr); - - for (SAPFOR::Argument* use : cur.uses) - { - if (!use || use->getType() != SAPFOR::CFG_ARG_TYPE::VAR) - continue; - - auto it = stRD.find(use); - if (it == stRD.end()) - continue; - - for (int defInstr : it->second) - { - if (defInstr < 0) - continue; - - auto itDef = defInstrToIdx.find(defInstr); - if (itDef != defInstrToIdx.end()) - addEdge(itDef->second, i); - } - } - } - - map> defsByVar; - for (int i = 0; i < n; ++i) - for (auto* d : infos[i].defs) - if (d && d->getType() == SAPFOR::CFG_ARG_TYPE::VAR) - defsByVar[d].push_back(i); - - for (auto& kv : defsByVar) - { - auto& list = kv.second; - sort(list.begin(), list.end()); - list.erase(unique(list.begin(), list.end()), list.end()); - for (int k = 0; k + 1 < (int)list.size(); ++k) - addEdge(list[k], list[k + 1]); - } - - map> defPositions; - for (auto& kv : defsByVar) - defPositions[kv.first] = kv.second; - - for (int i = 0; i < n; ++i) - { - for (SAPFOR::Argument* use : infos[i].uses) - { - if (!use || use->getType() != SAPFOR::CFG_ARG_TYPE::VAR) - continue; - - auto itDefs = defPositions.find(use); - if (itDefs == defPositions.end()) - continue; - - const auto& dpos = itDefs->second; - auto it = std::upper_bound(dpos.begin(), dpos.end(), i); - if (it != dpos.end()) - addEdge(i, *it); - } - } - - for (int u = 0; u < n; ++u) - { - auto& out = succ[u]; - sort(out.begin(), out.end()); - out.erase(unique(out.begin(), out.end()), out.end()); - } - fill(indeg.begin(), indeg.end(), 0); - for (int u = 0; u < n; ++u) - for (int v : succ[u]) - indeg[v]++; - - vector scheduled; - vector original = region; - if (!topoSchedule(original, succ, indeg, scheduled)) - { - region.clear(); - return; - } - - if (applyReorderContiguous(loop, original, scheduled)) - anyChange = true; - - region.clear(); - }; - - SgStatement* current = loopStart; - set visited; - - while (current && current != loopEnd) - { - if (!visited.insert(current).second) - break; - - if (isLoopBoundary(current)) - { - flushRegion(); - current = current->lexNext(); - continue; - } - - if (current->variant() == FOR_NODE && current != loop) - { - flushRegion(); - SgStatement* nestedEnd = current->lastNodeOfStmt(); - current = nestedEnd ? nestedEnd->lexNext() : current->lexNext(); - continue; - } - - if (!isSgExecutableStatement(current) || control_tags.count(current->variant())) - { - flushRegion(); - current = current->lexNext(); - continue; - } - - const bool isTopLevel = (current->controlParent() == loop); - if (isTopLevel && current->variant() == ASSIGN_STAT && canSafelyExtract(current, loop)) - { - auto irs = findInstructionsFromStatement(current, blocks); - set uses, defs; - bool spansMultiple = false; - if (isMovableStmtIR(irs, uses, defs, spansMultiple) && !spansMultiple) - { - region.push_back(current); - current = current->lexNext(); - continue; - } - } - - flushRegion(); - current = current->lexNext(); - } - - flushRegion(); - return anyChange; -} - vector findFuncBlocksByFuncStatement(SgStatement *st, const map>& FullIR) { vector result; Statement* forSt = (Statement*)st; @@ -721,34 +96,6 @@ map> findAndAnalyzeLoops(SgStatement *st 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(); - } - } - - reorderMovableRegionsInLoop(loop, blocks); -} - vector findBlocksInLoopsByFullIR( SgStatement* funcStmt, @@ -1204,8 +551,6 @@ static bool reorderOperatorsInBasicBlockUsingDeps(SAPFOR::BasicBlock* bb) void moveOperators(SgFile *file, map>& loopGraph, const map>& FullIR, int& countOfTransform) { - // countOfTransform += 1; - if (!file) return; @@ -1222,11 +567,5 @@ void moveOperators(SgFile *file, map>& loopGraph, if (reorderOperatorsInBasicBlockUsingDeps(bb)) countOfTransform += 1; } - - // vector blocks = findFuncBlocksByFuncStatement(st, FullIR); - // map> loopsMapping = findAndAnalyzeLoops(st, blocks); - - // for (auto& loopForAnalyze : loopsMapping) - // processLoopRecursively(loopForAnalyze.first, loopForAnalyze.second, FullIR); } } \ No newline at end of file From 0a484e77de02d6507ecfc22b71088290949546a2 Mon Sep 17 00:00:00 2001 From: ALEXks Date: Tue, 10 Mar 2026 10:03:27 +0300 Subject: [PATCH 5/5] version updated --- src/Utils/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils/version.h b/src/Utils/version.h index 7abff06..e6da384 100644 --- a/src/Utils/version.h +++ b/src/Utils/version.h @@ -1,3 +1,3 @@ #pragma once -#define VERSION_SPF "2468" +#define VERSION_SPF "2469"