in vm/jitrino/src/optimizer/osr.cpp [68:199]
OSROpndInfo OSRInductionDetector::processOpnd(LoopTree* tree,
LoopNode* loopHead,
InstStack& defStack,
const Opnd* opnd,
iv_detection_flag flag){
if (Log::isEnabled()) {
Log::out() << "Processing opnd: ";
opnd->print(Log::out());
Log::out() << "\n";
}
OSROpndInfo result;
Inst* defInst = opnd->getInst();
if (std::find(defStack.begin(), defStack.end(), defInst) !=
defStack.end()) {
result.setType(OSROpndInfo::COUNTER);
result.setIncrement(0);
result.setOpnd((Opnd*) opnd);
return result;
}
Opcode opcode = defInst->getOpcode();
if (opcode == Op_LdConstant) {
result.setType(OSROpndInfo::LD_CONST);
result.setConst(defInst->asConstInst()->getValue().i4);
result.setOpnd((Opnd*) opnd);
result.setHeader((Opnd*) opnd);
result.setHeaderFound();
return result;
}
if (!inExactLoop(tree, (Opnd*) opnd, loopHead)) {
result.setOpnd((Opnd*) opnd);
result.setHeader((Opnd*) opnd);
result.setHeaderFound();
return result;
}
defStack.push_back(defInst);
if (opcode == Op_Phi) {
OSROpndInfo info1 =
processOpnd(tree, loopHead, defStack, defInst->getSrc(0));
if (defInst->getNumSrcOperands() > 1) {
OSROpndInfo info2 =
processOpnd(tree, loopHead, defStack, defInst->getSrc(1));
if ( ((info1.isCounter() && !info1.isPhiSplit())
&& (info2.isDOL() || info2.isLDConst()))
|| ((info2.isCounter() && !info2.isPhiSplit())
&& (info1.isDOL() || info1.isLDConst())) ) {
result.setType(OSROpndInfo::COUNTER);
result.setIncrement(info1.isCounter()? info1.
getIncrement() : info2.getIncrement());
result.markPhiSplit();
result.setHeader((Opnd*) opnd);
result.setHeaderFound();
} else if ((flag == CHOOSE_MAX_IN_BRANCH) && info1.isCounter()
&& info2.isCounter()
&& signof(info1.getIncrement()) ==
signof(info2.getIncrement())) {
result.setType(OSROpndInfo::COUNTER);
result.setIncrement(std::abs(info1.getIncrement()) >
std::abs(info2.getIncrement())? info1.
getIncrement() : info2.getIncrement());
result.markPhiSplit();
result.setHeader((Opnd*) opnd);
result.setHeaderFound();
} else {
result.setType(OSROpndInfo::UNDEF);
}
}
} else if (opcode == Op_Add || opcode == Op_Sub) {
Opnd* opnd1 = defInst->getSrc(0);
Opnd* opnd2 = defInst->getSrc(1);
OSROpndInfo info1 = processOpnd(tree, loopHead, defStack, opnd1);
OSROpndInfo info2 = processOpnd(tree, loopHead, defStack, opnd2);
if ((info1.isLDConst() || info1.isDOL())
&& (info2.isLDConst() || info2.isDOL())) {
if (info1.isLDConst() && info2.isLDConst()
&& info1.getConst() == info2.getConst()) {
result.setType(OSROpndInfo::LD_CONST);
result.setConst(info1.getConst());
writeHeaderToResult(result, tree, info1, info2);
}
} else if ((info1.isCounter() && info2.isLDConst())
|| (info2.isCounter() && info1.isLDConst())) {
U_32 increment = info1.isCounter() ?
info1.getIncrement() : info2.getIncrement();
U_32 diff = info1.isLDConst()? info1.getConst() : info2.getConst();
bool monotonousFlag = increment == 0 || diff == 0
|| (opcode == Op_Add && signof(diff) == signof(increment))
|| (opcode == Op_Sub && signof(diff) != signof(increment));
if (monotonousFlag) {
result.setType(OSROpndInfo::COUNTER);
if ((info1.isCounter() && info1.isPhiSplit()) ||
(info2.isCounter() && info2.isPhiSplit())) {
result.markPhiSplit();
writeHeaderToResult(result, tree, info1, info2);
}
if (opcode == Op_Add) {
result.setIncrement(increment + diff);
writeHeaderToResult(result, tree, info1, info2);
} else {
result.setIncrement(increment - diff);
writeHeaderToResult(result, tree, info1, info2);
}
} else {
result.setType(OSROpndInfo::UNDEF);
}
} else {
result.setType(OSROpndInfo::UNDEF);
}
} else if (opcode == Op_StVar || opcode == Op_LdVar) {
Opnd* newOpnd = defInst->getSrc(0);
result = processOpnd(tree, loopHead, defStack, newOpnd);
} else if (opcode == Op_TauArrayLen) {
Opnd* arrayOpnd = defInst->getSrc(0);
result = processOpnd(tree, loopHead, defStack, arrayOpnd);
} else {
result.setType(OSROpndInfo::UNDEF);
}
defStack.pop_back();
result.setOpnd((Opnd*) opnd);
return result;
}