From d5eeceef9e4fef052afbd409a01fd8556b74b4e5 Mon Sep 17 00:00:00 2001 From: Egor Mayorov Date: Wed, 6 May 2026 19:49:54 +0300 Subject: [PATCH] dependencies from func calls --- src/Sapfor.cpp | 4 +- .../FunctionPurifying/function_purifying.cpp | 13 ++ .../FunctionPurifying/function_purifying.h | 2 + .../MoveOperators/move_operators.cpp | 134 +++++++++++++++++- .../MoveOperators/move_operators.h | 5 +- 5 files changed, 152 insertions(+), 6 deletions(-) diff --git a/src/Sapfor.cpp b/src/Sapfor.cpp index 96c129f..ead1240 100644 --- a/src/Sapfor.cpp +++ b/src/Sapfor.cpp @@ -943,8 +943,8 @@ static bool runAnalysis(SgProject &project, const int curr_regime, const bool ne internalExit = err; } } - else if (curr_regime == MOVE_OPERATORS) - moveOperators(file, fullIR, countOfTransform); + else if (curr_regime == MOVE_OPERATORS) + moveOperators(file, fullIR, allFuncInfo, countOfTransform); else if (curr_regime == PRIVATE_REMOVING_ANALYSIS) { auto itFound = loopGraph.find(file->filename()); diff --git a/src/Transformations/FunctionPurifying/function_purifying.cpp b/src/Transformations/FunctionPurifying/function_purifying.cpp index 0e8b03e..2d26677 100644 --- a/src/Transformations/FunctionPurifying/function_purifying.cpp +++ b/src/Transformations/FunctionPurifying/function_purifying.cpp @@ -2318,4 +2318,17 @@ static bool isIntrincis(const string& name) if (intrinsicF.find(name) != intrinsicF.end()) return true; return false; +} + +bool isPureIntrinsic(const string& name) +{ + if (!isIntrincis(name)) + return false; + + static const set intrinsicsThatMayWriteActualArgs = { + "cpu_time", + "etime", + "random_number", + }; + return intrinsicsThatMayWriteActualArgs.find(name) == intrinsicsThatMayWriteActualArgs.end(); } \ No newline at end of file diff --git a/src/Transformations/FunctionPurifying/function_purifying.h b/src/Transformations/FunctionPurifying/function_purifying.h index 6b0d6ad..11ec9ce 100644 --- a/src/Transformations/FunctionPurifying/function_purifying.h +++ b/src/Transformations/FunctionPurifying/function_purifying.h @@ -2,6 +2,8 @@ void insertIntrinsicStat(const std::vector& allFuncInfo); +bool isPureIntrinsic(const std::string& name); + bool checkOutCalls(const std::set& outCalls); std::map> fillFromIntent(SgStatement* header); void intentInsert(const std::vector& allFuncInfo); diff --git a/src/Transformations/MoveOperators/move_operators.cpp b/src/Transformations/MoveOperators/move_operators.cpp index ec468b5..dea1fbd 100644 --- a/src/Transformations/MoveOperators/move_operators.cpp +++ b/src/Transformations/MoveOperators/move_operators.cpp @@ -10,8 +10,10 @@ #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 "../FunctionPurifying/function_purifying.h" #include "move_operators.h" using namespace std; @@ -145,7 +147,26 @@ static vector findBlocksInLoopsByFullIR( return result; } -static map> analyzeBasicBlockIntraDependencies(const SAPFOR::BasicBlock* bb) +static map buildBasicBlockOwnerMap( + const map>& fullIR) +{ + map owners; + for (const auto& kv : fullIR) + { + FuncInfo* fi = kv.first; + if (!fi) + continue; + for (SAPFOR::BasicBlock* bb : kv.second) + if (bb) + owners[bb] = fi; + } + return owners; +} + +static map> analyzeBasicBlockIntraDependencies( + const SAPFOR::BasicBlock* bb, + FuncInfo* caller, + const map& funcMapByName) { if (!bb) return {}; @@ -422,6 +443,97 @@ static map> analyzeBasicBlockIntraDependencies(c map varUsages; map> operatorsDependencies; + function applyOutputEffectsFromRhs = + [&](SgExpression* expr, SgStatement* stmt) + { + if (!expr || !stmt || !caller) + return; + + if (isSgValueExp(expr) || expr->variant() == CONST_REF) + return; + + if (expr->variant() == FUNC_CALL) + { + auto* fcall = isSgFunctionCallExp(expr); + if (fcall) + { + FuncInfo* callee = nullptr; + string resolvedCalleeName; + for (const auto& cd : caller->callsFromDetailed) + { + if (cd.pointerDetailCallsFrom.first != static_cast(expr)) + continue; + if (cd.pointerDetailCallsFrom.second != FUNC_CALL) + continue; + resolvedCalleeName = cd.detailCallsFrom.first; + if (!cd.detailCallsFrom.first.empty()) + callee = getFuncInfo(funcMapByName, cd.detailCallsFrom.first); + break; + } + + if (resolvedCalleeName.empty() && fcall->symbol()) + { + SgSymbol* sym = OriginalSymbol(fcall->symbol()); + if (sym && sym->identifier()) + resolvedCalleeName = sym->identifier(); + } + + if (!callee && !resolvedCalleeName.empty()) + callee = getFuncInfo(funcMapByName, resolvedCalleeName); + + string lowerCalleeName = resolvedCalleeName; + for (char& c : lowerCalleeName) + c = static_cast(tolower(static_cast(c))); + + const bool unknownCalleeTreatAsPureIntrinsic = + !callee && !lowerCalleeName.empty() && isPureIntrinsic(lowerCalleeName); + + const int nArgs = fcall->numberOfArgs(); + for (int i = 0; i < nArgs; ++i) + { + bool mayModify = false; + if (callee) + { + if (i >= callee->funcParams.countOfPars) + mayModify = true; + else + mayModify = callee->funcParams.isArgOut(i) + || callee->funcParams.isArgInOut(i); + } + else if (unknownCalleeTreatAsPureIntrinsic) + mayModify = false; + else + mayModify = true; + + if (!mayModify) + continue; + + set argKeys; + collectUsedKeysFromExpression(fcall->arg(i), argKeys); + for (const string& k : argKeys) + varDeclarations[k] = stmt; + } + + for (int i = 0; i < nArgs; ++i) + applyOutputEffectsFromRhs(fcall->arg(i), stmt); + } + return; + } + + if (auto* arrayRef = isSgArrayRefExp(expr)) + { + for (int i = 0; i < arrayRef->numberOfSubscripts(); ++i) + applyOutputEffectsFromRhs(arrayRef->subscript(i), stmt); + return; + } + + if (expr->variant() == VAR_REF) + return; + + applyOutputEffectsFromRhs(expr->lhs(), stmt); + applyOutputEffectsFromRhs(expr->rhs(), stmt); + }; + for (SgStatement* stmt : operatorsOrder) { set usedKeys; @@ -436,6 +548,9 @@ static map> analyzeBasicBlockIntraDependencies(c if (!declarationKey.empty()) varDeclarations[declarationKey] = stmt; + if (stmt && caller) + applyOutputEffectsFromRhs(stmt->expr(1), stmt); + for (const string& key : usedKeys) varUsages[key] = stmt; } @@ -638,18 +753,31 @@ static bool reorderOperatorsInBasicBlockUsingDeps( return true; } -void moveOperators(SgFile* file, const map>& FullIR, int& countOfTransform) { +void moveOperators(SgFile* file, + const map>& FullIR, + const map>& allFuncInfo, + int& countOfTransform) +{ if (!file) return; if (SgFile::switchToFile(file->filename()) == -1) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); + + map funcMap; + createMapOfFunc(allFuncInfo, funcMap); + const map blockOwner = buildBasicBlockOwnerMap(FullIR); + const auto loopBlocks = findBlocksInLoopsByFullIR(file, FullIR); for (auto* bb : loopBlocks) { if (!bb) continue; - const auto operatorsDependencies = analyzeBasicBlockIntraDependencies(bb); + FuncInfo* caller = nullptr; + auto itOwn = blockOwner.find(bb); + if (itOwn != blockOwner.end()) + caller = itOwn->second; + const auto operatorsDependencies = analyzeBasicBlockIntraDependencies(bb, caller, funcMap); if (reorderOperatorsInBasicBlockUsingDeps(bb, operatorsDependencies)) countOfTransform += 1; } diff --git a/src/Transformations/MoveOperators/move_operators.h b/src/Transformations/MoveOperators/move_operators.h index 4ee8f98..db9dd34 100644 --- a/src/Transformations/MoveOperators/move_operators.h +++ b/src/Transformations/MoveOperators/move_operators.h @@ -3,4 +3,7 @@ #include "../../GraphLoop/graph_loops.h" #include "../../CFGraph/CFGraph.h" -void moveOperators(SgFile* file, const std::map>& FullIR, int& countOfTransform); +void moveOperators(SgFile* file, + const std::map>& FullIR, + const std::map>& allFuncInfo, + int& countOfTransform);