WIP change logic of inductive variables

This commit is contained in:
2025-06-19 23:01:10 +03:00
parent 375070f959
commit 2af6d9c140
2 changed files with 73 additions and 297 deletions

View File

@@ -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"

View File

@@ -146,312 +146,89 @@ void getLoopBody(SAPFOR::BasicBlock* loopHeader, const std::set<SAPFOR::BasicBlo
}
}
SAPFOR::Instruction* findDef(const SAPFOR::Argument* arg,
const std::vector<SAPFOR::BasicBlock*>& blocks) {
if (!arg) return nullptr;
std::string argName = arg->getValue();
set<SAPFOR::Argument*> findRegisterSourceVariables(const std::vector<SAPFOR::BasicBlock*>& blocks, SAPFOR::Argument* var) {
std::set<SAPFOR::Argument*> result;
std::set<SAPFOR::Argument*> visited;
std::stack<SAPFOR::Argument*> 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<SAPFOR::Instruction*> getPhiArguments(SAPFOR::BasicBlock* block, SAPFOR::Instruction* phiInstr) {
std::vector<SAPFOR::Instruction*> 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<SAPFOR::BasicBlock*>& 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<SAPFOR::BasicBlock*>& blocks) {
for (auto block : blocks) {
for (auto instrWrapper : block->getInstructions()) {
auto instr = instrWrapper->getInstruction();
if (instr->getNumber() == number) {
return block;
}
}
}
return nullptr;
}
set<SAPFOR::Argument*> findSourceVariablesRecursive(const std::vector<SAPFOR::BasicBlock*>& blocks, SAPFOR::Argument* var) {
std::set<SAPFOR::Argument*> result;
std::set<SAPFOR::Argument*> visited;
std::stack<SAPFOR::Argument*> 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<std::string> traceRecursiveSources(const std::vector<SAPFOR::BasicBlock*>& blocks, SAPFOR::Argument* arg) {
std::set<std::string> result;
std::set<SAPFOR::Argument*> visited;
std::stack<SAPFOR::Argument*> 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<std::string> traceSourcesDeepToPhi(const std::vector<SAPFOR::BasicBlock*>& blocks, SAPFOR::Argument* arg, const std::set<std::string>& phiNames) {
std::set<std::string> reachedPhi;
std::set<SAPFOR::Argument*> visited;
std::stack<SAPFOR::Argument*> 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<SAPFOR::BasicBlock*>& blocks,
const std::vector<SAPFOR::BasicBlock*>& Loopblocks,
SAPFOR::BasicBlock* loopHeader,
const std::set<SAPFOR::BasicBlock*>& loopExits) {
std::set<std::string> inductiveVars;
std::set<SAPFOR::BasicBlock*> 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<std::string> 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<SAPFOR::BasicBlock*>& 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<SAPFOR::BasicBlock*>& Loopblocks, const std::vector<SAPFOR::BasicBlock*>& blocks) {
std::set<std::string> 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<SAPFOR::BasicBlock*>& loopBody) {
std::set<SAPFOR::BasicBlock*> loopSet(loopBody.begin(), loopBody.end());
@@ -473,7 +250,7 @@ Instruction* findInstructionAfterLoop(const std::vector<SAPFOR::BasicBlock*>& lo
}
}
return nullptr; // не нашли
return nullptr;
}
bool isEqual(const char* cstr, const std::string& str) {
@@ -494,8 +271,8 @@ void findImplicitLoops(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*
|| isEqual("decod3.for", i.first->fileName))
continue;
/*if (!isEqual("ddst2.for", i.first->fileName))
continue;*/
//if (!isEqual("iter3.for", i.first->fileName))
// continue;
map<int, int> visited;
for (auto i : i.second)
@@ -504,7 +281,7 @@ void findImplicitLoops(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*
//for (auto j : i.second)
// printBlock(j);
//continue;
//vector<int> visited(i.second.size(), UNVISITED);
vector<pair<SAPFOR::BasicBlock*, SAPFOR::BasicBlock*>> startAndEnd;
@@ -535,7 +312,7 @@ void findImplicitLoops(const std::map<FuncInfo*, std::vector<SAPFOR::BasicBlock*
//}
//cout << endl;
findInductiveVars(i.second, loopBody, header, loopExits);
findInductiveVars(loopBody, i.second);
continue;