void PiBoundIter::setCurrent()

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;
    }
}