• motonik's avatar
    BIV · 4b2f8c0e
    motonik authored
    4b2f8c0e
LoopIndVar.cpp 6.79 KiB
#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; }