in vm/jitrino/src/optimizer/abcd/abcdbounds.cpp [614:907]
void PiBoundIter::setCurrent()
{
if (isEmpty()) return;
if (!instr) return;
switch (instr->getOpcode()) {
case Op_Phi:
{
if (idx >= instr->getNumSrcOperands()) {
instr = 0;
if (why) why->clear();
} else {
Opnd *srci = instr->getSrc(idx);
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
if (why) why->clear();
}
}
break;
case Op_TauPi:
{
// first, try to insert condition
TauPiInst *pInst = instr->asTauPiInst();
const PiCondition *cond = pInst->getCond();
Opnd *tauDepOpnd = pInst->getSrc(1);
SsaTmpOpnd *tauDep = tauDepOpnd->asSsaTmpOpnd();
assert(tauDep);
if (isLb) {
current = cond->getLb();
} else {
current = cond->getUb();
}
assert(!current.isUnknown());
if (current.isUndefined() && (idx >= 1)) {
instr = 0;
} else if ((!current.isUndefined()) && (idx == 0)) {
// use the Pi condition
if (why) why->addReason(tauDep);
} else if (idx <= 1) {
// effect of assignment
Opnd *srci = instr->getSrc(0);
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
} else {
instr = 0;
}
}
break;
case Op_Add:
if (idx > 0) instr = 0;
else {
Opnd *op0 = instr->getSrc(0);
Opnd *op1 = instr->getSrc(1);
Opnd *constOpnd0 = getConstantOpnd(op0);
Opnd *constOpnd1 = getConstantOpnd(op1);
if ((constOpnd0 || constOpnd1)
&& (instr->getType() == Type::Int32)) {
int64 c;
// I assume we've done folding first
assert(!(constOpnd0 && constOpnd1));
if (constOpnd1) {
// swap the operands;
constOpnd0 = constOpnd1;
op1 = op0;
}
// now constOpnd0 is the constant opnd
// op1 is the non-constant opnd
Inst *inst0 = constOpnd0->getInst();
assert(inst0);
ConstInst *cinst0 = inst0->asConstInst();
assert(cinst0);
ConstInst::ConstValue cv = cinst0->getValue();
c = cv.i4;
VarBound vb(op1);
current = PiBound(instr->getType(), 1, vb, c);
} else
instr = 0;
}
break;
case Op_Sub:
if (idx > 0) instr = 0;
else {
Opnd *constOpnd = getConstantOpnd(instr->getSrc(1));
if (constOpnd
&& (instr->getType() == Type::Int32)) {
#ifndef NDEBUG
Opnd *op0 = instr->getSrc(0);
#endif
Opnd *op1 = constOpnd;
// now op1 should be constant
// I assume we've done folding first
assert(!getConstantOpnd(op0));
Inst *inst1 = op1->getInst();
assert(inst1);
ConstInst *cinst1 = inst1->asConstInst();
assert(cinst1);
ConstInst::ConstValue cv = cinst1->getValue();
I_32 c = cv.i4;
I_32 negc = -c;
if (neg_overflowed(negc,c)) { // overflowed
instr = 0;
} else {
VarBound vb(op1);
current = PiBound(instr->getType(), 1, vb, negc);
}
} else
instr = 0;
}
break;
case Op_Min:
if ((idx == 0) || (idx == 1)) {
Opnd *srci = instr->getSrc(idx); // the source operand
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
} else {
instr = 0;
}
break;
case Op_Max:
if ((idx == 0) || (idx == 1)) {
Opnd *srci = instr->getSrc(idx); // the source operand
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
} else {
instr = 0;
}
break;
case Op_Abs:
if (idx == 0) {
ConstBound cb((int64)0);
current = PiBound(instr->getType(), (int64) 0);
} else {
instr = 0;
}
break;
case Op_TauCheckBounds:
assert(0);
switch (idx) {
case 0:
{
Opnd *srci = instr->getSrc(1); // the index in;
VarBound vb(srci);
current = PiBound(srci->getType()->tag, vb); // result bounded by input index
}
break;
case 1:
if (isLb) {
current = PiBound(instr->getType(), int64(0)); // and 0
} else {
// the array length
Opnd *srci = instr->getSrc(0); // the array length
VarBound vb(srci);
current = PiBound(srci->getType()->tag, int64(1), vb, int64(-1)); // len - 1
}
break;
default:
instr = 0;
break;
};
break;
case Op_Copy:
if (idx == 0) {
Opnd *srci = instr->getSrc(0); // the source operand
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
} else {
instr = 0;
}
break;
case Op_LdVar:
if (idx == 0) {
assert(instr->isVarAccess());
VarAccessInst *varInst = (VarAccessInst *)instr;
Opnd *srci = varInst->getSrc(0);
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
} else {
instr = 0;
}
break;
case Op_StVar:
if (idx == 0) {
assert(instr->isVarAccess());
Opnd *srci = instr->getSrc(0);
VarBound vb(srci);
current = PiBound(instr->getType(), vb);
} else {
instr = 0;
}
break;
case Op_TauArrayLen:
if (idx == 0) {
if (isLb) {
// 0
current = PiBound(instr->getType(), int64(0));
} else {
current = PiBound(instr->getType(), int64(0x7fffffff)); // bounded by max int
}
} else {
instr = 0;
}
break;
case Op_LdConstant:
if (idx == 0) {
ConstInst *cinst0 = instr->asConstInst();
if (!PiBound::extractConstant(instr->getType(), cinst0, current)) {
instr = 0;
}
} else {
instr = 0;
}
break;
// could maybe do something with these:
case Op_TauRem:
if (idx == 0) {
Opnd *denom = instr->getSrc(1);
if (getConstantOpnd(denom)) {
Inst *consti1 = denom->getInst();
ConstInst *cinst1 = consti1->asConstInst();
assert(cinst1);
PiBound tmp(instr->getType(), true);
if (PiBound::extractConstant(instr->getType(), cinst1, current)) {
if (isLb) {
current = tmp.abs().neg();
} else {
current = tmp.abs();
}
}
} else {
instr = 0;
}
} else {
instr = 0;
}
break;
case Op_Conv:
if (idx == 0) {
Opnd *srci = instr->getSrc(0); // the source operand
Type::Tag srcType = srci->getType()->tag;
Type::Tag dstType = instr->getDst()->getType()->tag;
Type::Tag instrType = instr->getType();
PiCondition bounds = PiCondition::typeBounds(dstType, srcType);
PiCondition bounds2 = bounds.cast(instrType);
PiCondition bounds3 = bounds.cast(dstType);
if (isLb) {
current = bounds3.getLb();
} else {
current = bounds3.getUb();
}
} else {
instr = 0;
}
break;
case Op_Cmp:
if (idx == 0) {
current = PiBound(instr->getType(), int64(isLb ? 0 : 1));
} else {
instr = 0;
}
break;
case Op_Cmp3:
if (idx == 0) {
current = PiBound(instr->getType(), int64(isLb ? -1 : 1));
} else {
instr = 0;
}
break;
case Op_TauCheckNull:
case Op_TauCheckZero:
case Op_TauCheckCast:
case Op_TauHasType:
case Op_TauHasExactType:
case Op_TauIsNonNull:
assert(0);
break;
case Op_Or:
case Op_Not:
case Op_Neg:
case Op_DefArg:
case Op_NewArray:
case Op_TauCast:
case Op_TauAsType:
default:
instr = 0 ;
break;
}
}