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