From 2af6d9c14073226e4257b681cd9130f34c7818e5 Mon Sep 17 00:00:00 2001 From: Dudarenko Date: Thu, 19 Jun 2025 23:01:10 +0300 Subject: [PATCH] WIP change logic of inductive variables --- src/CFGraph/IR_SSAForm.cpp | 1 - src/LoopAnalyzer/implicit_loops_analyzer.cpp | 369 ++++--------------- 2 files changed, 73 insertions(+), 297 deletions(-) diff --git a/src/CFGraph/IR_SSAForm.cpp b/src/CFGraph/IR_SSAForm.cpp index 91cd435..117cb60 100644 --- a/src/CFGraph/IR_SSAForm.cpp +++ b/src/CFGraph/IR_SSAForm.cpp @@ -6,7 +6,6 @@ #include "../Utils/SgUtils.h" #include "../Utils/CommonBlock.h" #include "../GraphCall/graph_calls.h" -#include "../ExpressionTransform/expr_transform.h" #include "dvm.h" #include "IR.h" diff --git a/src/LoopAnalyzer/implicit_loops_analyzer.cpp b/src/LoopAnalyzer/implicit_loops_analyzer.cpp index 94f047f..e2dbd30 100644 --- a/src/LoopAnalyzer/implicit_loops_analyzer.cpp +++ b/src/LoopAnalyzer/implicit_loops_analyzer.cpp @@ -146,312 +146,89 @@ void getLoopBody(SAPFOR::BasicBlock* loopHeader, const std::set& blocks) { + if (!arg) return nullptr; + std::string argName = arg->getValue(); -set findRegisterSourceVariables(const std::vector& blocks, SAPFOR::Argument* var) { - std::set result; - std::set visited; - std::stack workStack; - workStack.push(var); - - auto isBinaryOp = [](SAPFOR::CFG_OP op) { - return op == SAPFOR::CFG_OP::ADD || op == SAPFOR::CFG_OP::SUBT || - op == SAPFOR::CFG_OP::MULT || op == SAPFOR::CFG_OP::DIV || - op == SAPFOR::CFG_OP::POW || - op == SAPFOR::CFG_OP::GE || op == SAPFOR::CFG_OP::LE || - op == SAPFOR::CFG_OP::GT || op == SAPFOR::CFG_OP::LT || - op == SAPFOR::CFG_OP::EQ || op == SAPFOR::CFG_OP::NEQV || - op == SAPFOR::CFG_OP::EQV || op == SAPFOR::CFG_OP::EMPTY || - op == SAPFOR::CFG_OP::OR || op == SAPFOR::CFG_OP::AND; - }; - - auto isUnaryOp = [](SAPFOR::CFG_OP op) { - return op == SAPFOR::CFG_OP::UN_ADD || op == SAPFOR::CFG_OP::UN_MINUS || - op == SAPFOR::CFG_OP::NOT || op == SAPFOR::CFG_OP::ASSIGN; - }; - - while (!workStack.empty()) { - auto variable = workStack.top(); - workStack.pop(); - if (!variable || visited.count(variable)) - continue; - - visited.insert(variable); - - for (auto block : blocks) { - for (auto instrWrapper : block->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (!instr || instr->getResult() != variable) - continue; - - auto op = instr->getOperation(); - auto arg1 = instr->getArg1(); - auto arg2 = instr->getArg2(); - - if (isBinaryOp(op) && arg1 && arg2) { - if (arg1->getType() == CFG_ARG_TYPE::VAR) - result.insert(arg1); - else if (arg1->getType() == CFG_ARG_TYPE::REG) - workStack.push(arg1); - - if (arg2->getType() == CFG_ARG_TYPE::VAR) - result.insert(arg2); - else if (arg2->getType() == CFG_ARG_TYPE::REG) - workStack.push(arg2); - } - else if (isUnaryOp(op) && arg1) { - if (arg1->getType() == CFG_ARG_TYPE::VAR) - result.insert(arg1); - else if (arg1->getType() == CFG_ARG_TYPE::REG) - workStack.push(arg1); - } - } - } - } - - return result; -} - -std::vector getPhiArguments(SAPFOR::BasicBlock* block, SAPFOR::Instruction* phiInstr) { - std::vector result; - - auto& instructions = block->getInstructions(); - bool collecting = false; - for (int i = instructions.size() - 1; i >= 0; --i) { - auto instr = instructions[i]->getInstruction(); - - if (collecting) { - if (instr->getOperation() == SAPFOR::CFG_OP::PARAM) { - auto arg = instr->getArg1(); - if (arg) { - result.push_back(instr); - } - } - else { - break; - } - } - - if (!instr) continue; - - if (instr == phiInstr) { - collecting = true; - continue; - } - } - - std::reverse(result.begin(), result.end()); - return result; -} - -SAPFOR::BasicBlock* findInstructionBlock(SAPFOR::Instruction* targetInstr, const std::vector& blocks) { for (auto block : blocks) { - for (auto instrWrapper : block->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (instr == targetInstr) { - return block; - } - } - } - return nullptr; -} - -SAPFOR::BasicBlock* findInstructionBlockByNumber(int number, const std::vector& blocks) { - for (auto block : blocks) { - for (auto instrWrapper : block->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (instr->getNumber() == number) { - return block; - } - } - } - return nullptr; -} - -set findSourceVariablesRecursive(const std::vector& blocks, SAPFOR::Argument* var) { - std::set result; - std::set visited; - std::stack workStack; - workStack.push(var); - - while (!workStack.empty()) { - auto variable = workStack.top(); workStack.pop(); - if (!variable || visited.count(variable)) continue; - visited.insert(variable); - - bool foundDefinition = false; - for (auto block : blocks) { - for (auto instrWrapper : block->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (!instr || instr->getResult() != variable) continue; - - foundDefinition = true; - auto arg1 = instr->getArg1(); - auto arg2 = instr->getArg2(); - if (arg1 && arg1->getType() == CFG_ARG_TYPE::VAR) result.insert(arg1); - if (arg1 && arg1->getType() == CFG_ARG_TYPE::REG) workStack.push(arg1); - if (arg2 && arg2->getType() == CFG_ARG_TYPE::VAR) result.insert(arg2); - if (arg2 && arg2->getType() == CFG_ARG_TYPE::REG) workStack.push(arg2); - } - } - if (!foundDefinition) result.insert(variable); // параметр - } - - return result; -} - -// Версия findInductiveVars без логов, только финальная статистика - -// Версия findInductiveVars с расширенной поддержкой и анализом цепочек зависимостей через регистры и другие операции - -std::set traceRecursiveSources(const std::vector& blocks, SAPFOR::Argument* arg) { - std::set result; - std::set visited; - std::stack stack; - stack.push(arg); - - while (!stack.empty()) { - auto curr = stack.top(); stack.pop(); - if (!curr || visited.count(curr)) continue; - visited.insert(curr); - - if (curr->getType() == CFG_ARG_TYPE::VAR) { - result.insert(curr->getValue()); - continue; - } - - for (auto block : blocks) { - for (auto instrWrapper : block->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (!instr) continue; - if (instr->getResult() != curr) continue; - - auto a1 = instr->getArg1(); - auto a2 = instr->getArg2(); - if (a1) stack.push(a1); - if (a2) stack.push(a2); - } - } - } - - return result; -} - -// Улучшенная версия с трассировкой цепочек регистров до phi-переменных - -std::set traceSourcesDeepToPhi(const std::vector& blocks, SAPFOR::Argument* arg, const std::set& phiNames) { - std::set reachedPhi; - std::set visited; - std::stack stack; - stack.push(arg); - - while (!stack.empty()) { - auto curr = stack.top(); stack.pop(); - if (!curr || visited.count(curr)) continue; - visited.insert(curr); - - //std::cout << "[DEBUG] visiting " - // << (curr->getType() == CFG_ARG_TYPE::VAR ? "VAR" : - // curr->getType() == CFG_ARG_TYPE::REG ? "REG" : "OTHER") - // << ": ." << curr->getValue() << "." << std::endl; - - if (phiNames.count(curr->getValue())) { - //std::cout << "[DEBUG] REACHED phi: ." << curr->getValue() << "." << std::endl; - reachedPhi.insert(curr->getValue()); - continue; - } - - for (auto block : blocks) { - for (auto instrWrapper : block->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (!instr) continue; - if (instr->getResult() != curr) continue; - - auto a1 = instr->getArg1(); - auto a2 = instr->getArg2(); - if (a1) stack.push(a1); - if (a2) stack.push(a2); - } - } - } - return reachedPhi; -} - -void findInductiveVars(const std::vector& blocks, - const std::vector& Loopblocks, - SAPFOR::BasicBlock* loopHeader, - const std::set& loopExits) { - std::set inductiveVars; - std::set relevantBlocks = { loopHeader }; - - for (auto block : relevantBlocks) { for (auto instrWrapper : block->getInstructions()) { auto instr = instrWrapper->getInstruction(); if (!instr) continue; - auto op = instr->getOperation(); auto res = instr->getResult(); - auto arg1 = instr->getArg1(); - auto arg2 = instr->getArg2(); + if (!res) continue; - if (op == CFG_OP::JUMP_IF) { - if (arg1 && arg1->getType() == CFG_ARG_TYPE::VAR) { - inductiveVars.insert(arg1->getValue()); - } - if (arg1 && arg1->getType() == CFG_ARG_TYPE::REG) { - auto foundVariables = findRegisterSourceVariables(blocks, arg1); - for (auto var : foundVariables) { - inductiveVars.insert(var->getValue()); - } - } + if (res->getValue() == argName) { + return instr; } } } - std::set finalInductiveVars; - - for (auto instrWrapper : loopHeader->getInstructions()) { - auto instr = instrWrapper->getInstruction(); - if (!instr || instr->getOperation() != SAPFOR::CFG_OP::F_CALL || !instr->getArg1() || instr->getArg1()->getValue() != "FI_FUNCTION") continue; - - auto phiRes = instr->getResult(); - if (!phiRes || !inductiveVars.count(phiRes->getValue())) continue; - - auto currentBlock = findInstructionBlock(instr, blocks); - if (!currentBlock) continue; - - auto phiArgs = getPhiArguments(currentBlock, instr); - - bool hasInLoopDefinition = false; - - for (const auto& argInstr : phiArgs) { - if (!argInstr) continue; - - int definitionInstrNumber = std::stoi(argInstr->getArg1()->getValue()); - if (definitionInstrNumber == -1) continue; - - auto phiBlock = findInstructionBlockByNumber(definitionInstrNumber, blocks); - if (!phiBlock) continue; - - if (std::find(Loopblocks.begin(), Loopblocks.end(), phiBlock) != Loopblocks.end()) { - hasInLoopDefinition = true; - } - } - - if (hasInLoopDefinition) { - finalInductiveVars.insert(phiRes->getValue()); - } - } - - for (const auto& var : finalInductiveVars) { - std::cout << "Confirmed inductive variable: " << var << std::endl; - } - - if (finalInductiveVars.empty()) { - std::cout << "No confirmed inductive variables found." << std::endl; - } + return nullptr; } +const SAPFOR::Argument* getBaseSource(const SAPFOR::Argument* arg, const std::vector& blocks) { + while (arg && arg->getType() == CFG_ARG_TYPE::REG) { + auto defInstr = findDef(arg, blocks); + if (!defInstr) break; + auto defOp = defInstr->getOperation(); + if (defOp == CFG_OP::ASSIGN) { + arg = defInstr->getArg1(); + } + else { + break; + } + } + return arg; +} + +void findInductiveVars(const std::vector& Loopblocks, const std::vector& blocks) { + std::set inductiveVars; + + for (auto block : Loopblocks) { + for (auto instrWrapper : block->getInstructions()) { + auto instr = instrWrapper->getInstruction(); + if (!instr) continue; + + auto res = instr->getResult(); + if (!res || res->getType() != SAPFOR::CFG_ARG_TYPE::VAR) continue; + + while (instr && instr->getOperation() == CFG_OP::ASSIGN) { + instr = findDef(instr->getArg1(), blocks); + } + + if (!instr || instr->getOperation() != CFG_OP::ADD && instr->getOperation() != CFG_OP::SUBT) continue; + + auto arg1 = getBaseSource(instr->getArg1(), blocks); + auto arg2 = getBaseSource(instr->getArg2(), blocks); + + bool ok = false; + if (res->getValue() == arg1->getValue() && + arg2->getType() == CFG_ARG_TYPE::CONST) { + ok = true; + } + else if (res->getValue() == arg2->getValue() && + arg1->getType() == CFG_ARG_TYPE::CONST) { + ok = true; + } + + if (ok) { + inductiveVars.insert(res->getValue()); + } + } + } + + if (inductiveVars.empty()) { + std::cout << "No inductive variables found." << std::endl; + } + else { + for (const auto& var : inductiveVars) { + std::cout << "Inductive variable: " << var << std::endl; + } + } +} Instruction* findInstructionAfterLoop(const std::vector& loopBody) { std::set loopSet(loopBody.begin(), loopBody.end()); @@ -473,7 +250,7 @@ Instruction* findInstructionAfterLoop(const std::vector& lo } } - return nullptr; // не нашли + return nullptr; } bool isEqual(const char* cstr, const std::string& str) { @@ -494,8 +271,8 @@ void findImplicitLoops(const std::mapfileName)) continue; - /*if (!isEqual("ddst2.for", i.first->fileName)) - continue;*/ + //if (!isEqual("iter3.for", i.first->fileName)) + // continue; map visited; for (auto i : i.second) @@ -504,7 +281,7 @@ void findImplicitLoops(const std::map visited(i.second.size(), UNVISITED); vector> startAndEnd; @@ -535,7 +312,7 @@ void findImplicitLoops(const std::map