An error occurred while loading the file. Please try again.
-
motonik authored4b2f8c0e
#include "LoopIndVar.h"
#include "LoopDetection.h"
#include "LoopInvariantAnalysis.h"
using namespace ir;
bool LoopInductionVariableAnalysis::fitPattern(Ptr<PhiInst> phiNode, Value val, Value destReg, Ptr<Loop> loop) {
if (!val.isRegister()) {
return false;
}
if (phiNode->destReg() == val.getRegister()) {
for (auto inEdge : phiNode->parentBB()->inEdges()) {
if (inEdge->getCopySrcVal(phiNode) == destReg) {
continue;
} else {
if (loop->bbs().count(inEdge->src()) != 0) {
return false;
}
}
}
} else {
return false;
}
return true;
}
// TODO: handle the initial value of branching variable
// for example, if b = phi [a : a bb in the loop, others : b = a +/- c],
// then we can have the conclusion that a is the initial value of b is a +/- c
// so we need to handle the initial value of b that was defined outside of the loop
Value handleInitialValue(Ptr<PhiInst> phiNode, Value val, Value destReg, Ptr<Loop> loop) {
auto preHeaderBB = loop->preheaderBB();
if (!preHeaderBB || preHeaderBB == loop->headerBB()->parentFunc()->entryBB()) {
loop->createNewPreheaderBB();
}
if (phiNode->destReg() == val.getRegister()) {
for (auto inEdge : phiNode->parentBB()->inEdges()) {
if (inEdge->getCopySrcVal(phiNode) == destReg) {
continue; // skip the edge that comes from the loop
} else {
auto inBB = inEdge->src();
auto inVal = inEdge->getCopySrcVal(phiNode);
if (inVal.isLiteral()) {
return inVal;
}
}
}
}
return Value();
}
// we assume that all basic induction variable fit phi pattern*:
//
// phi pattern:
//
// ----------
// loop headerBB : phiNodes
// b = phi [a : a bb in the loop, others : none of them comes from a bb in the loop]
// ----------
// loop body : add or sub operInst
// a = b +/- e
// (e is invariant)
// ----------
// then we can have the conclusion that a and b are both basic induction variable
//
// so the way to inplement the algorithm to find basci induction variable :
// 1. find an add or sub instruction
// 2. look for loop headerBB's all inedge
// 3. confirm that only one edge comes from loop'bb
// the following function finds the basic induction variable in a loop
void LoopInductionVariableAnalysis::findBasicIndVar(Ptr<Loop> loop) {
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
Set<RegPtr> basicIndVars;
auto phiNodes = loop->headerBB()->getPhiNodes();
for (auto bb : loop->bbs()) {
for (auto inst : bb->getInstSet()) {
if (auto operInst = castPtr<OperInst>(inst)) {
if (operInst->isBinary()) {
if (operInst->op() == OperInst::Operator::Add || operInst->op() == OperInst::Operator::Sub) {
// try to fit phi pattern
if (this->invariantCtx->isInvariant(operInst->lhs()) && operInst->rhs().isRegister()) {
for (auto phiNode : phiNodes) {
if (fitPattern(phiNode, operInst->rhs(), operInst->destReg(), loop)) {
basicIndVars.insert(operInst->rhs().getRegister());
basicIndVars.insert(operInst->destReg());
BIVStep.insert({operInst->rhs().getRegister(), operInst->lhs()});
BIVStep.insert({operInst->destReg(), operInst->lhs()});
auto initialValue = handleInitialValue(phiNode, operInst->rhs(), operInst->destReg(), loop);
BIVIniVal.insert({operInst->rhs().getRegister(), initialValue});
BIVIniVal.insert({operInst->destReg(), initialValue});
}
}
} else if (this->invariantCtx->isInvariant(operInst->rhs()) && operInst->lhs().isRegister()) {
for (auto phiNode : phiNodes) {
if (fitPattern(phiNode, operInst->lhs(), operInst->destReg(), loop)) {
basicIndVars.insert(operInst->lhs().getRegister());
basicIndVars.insert(operInst->destReg());
BIVStep.insert({operInst->lhs().getRegister(), operInst->rhs()});
BIVStep.insert({operInst->destReg(), operInst->rhs()});
auto initialValue = handleInitialValue(phiNode, operInst->lhs(), operInst->destReg(), loop);
BIVIniVal.insert({operInst->lhs().getRegister(), initialValue});
BIVIniVal.insert({operInst->destReg(), initialValue});
}
}
}
}
}
}
}
}
this->basicIndVar = basicIndVars;
}
void LoopInductionVariableAnalysis::findIndVar(Ptr<Loop> loop) {
auto basicIndvars = this->basicIndVar;
Set<RegPtr> indVars = {basicIndvars.begin(), basicIndvars.end()};
FixedPoint([&](bool &changed) {
for (auto bb : loop->bbs()) {
for (auto inst : bb->getInstSet()) {
if (auto operInst = castPtr<OperInst>(inst)) {
if (operInst->isBinary() && (operInst->op() == OperInst::Operator::Add || operInst->op() == OperInst::Operator::Sub || operInst->op() == OperInst::Operator::Mul || operInst->op() == OperInst::Operator::Div)) {
// 检查操作数是否为归纳变量和循环不变量的组合
if (this->invariantCtx->isInvariant(operInst->lhs())) {
auto rhsReg = operInst->rhs().getRegister();
if (indVars.find(rhsReg) != indVars.end()) {
// 将新发现的归纳变量加入集合
if (indVars.insert(operInst->destReg()).second) {
changed = true; // 发现新的依赖归纳变量
}
}
} else if (this->invariantCtx->isInvariant(operInst->rhs())) {
auto lhsReg = operInst->lhs().getRegister();
if (indVars.find(lhsReg) != indVars.end()) {
if (indVars.insert(operInst->destReg()).second) {
changed = true;
}
}
}
}
}
141142143144145146147
}
}
},
/* debugPrint = */ true, "findIndVar");
this->allIndVar = indVars;
}