void InstValueNumberer::addInfoFromBranchCompare()

in vm/jitrino/src/optimizer/hashvaluenumberer.cpp [1967:2267]


void InstValueNumberer::addInfoFromBranchCompare(Node* targetNode, 
                                                 ComparisonModifier mod,
                                                 Type::Tag comparisonType,
                                                 bool isTrueEdge,
                                                 U_32 numSrcOperands,
                                                 Opnd *src0,
                                                 Opnd *src1)
{
    // add the branch
    ComparisonModifier modhere 
        = (isTrueEdge 
           ? mod 
           : negateComparison(mod, Type::isFloatingPoint(comparisonType)));
    ComparisonModifier negModhere = 
        negateComparison(modhere,
                         Type::isFloatingPoint(comparisonType));
    Operation cmpOperation(Op_Cmp, comparisonType, modhere);
    Operation negCmpOperation(Op_Cmp, comparisonType, negModhere);
    Operation branchOperation(Op_Branch, comparisonType, modhere);
    Operation negBranchOperation(Op_Branch, comparisonType, negModhere);
    switch (numSrcOperands) {
    case 1:
        {
            if (Log::isEnabled()) {
                Log::out() << "adding true comparison: ";
                switch (modhere) {
                case Cmp_Zero: Log::out() << "Cmp_Zero "; break;
                case Cmp_NonZero: Log::out() << "Cmp_NonZero "; break;
                default: assert(0); break;
                }
                src0->print(Log::out());
                Log::out() << ::std::endl;
                Log::out() << "branchOperation.hashcode() == "
                           << (int) branchOperation.encodeForHashing()
                           << ::std::endl;
                Log::out() << "cmpOperation.hashcode() == "
                           << (int) cmpOperation.encodeForHashing()
                           << ::std::endl;
            }
            Inst *tauEdge = getBlockTauEdge(targetNode)->getInst();
            setHashToInst(tauEdge, getKey(branchOperation, src0->getId()));
            setHashToInst(tauEdge, getKey(cmpOperation, src0->getId()));
            
            if (Log::isEnabled()) {
                Log::out() << "adding false comparison: ";
                switch (negModhere) {
                case Cmp_Zero: Log::out() << "Cmp_Zero "; break;
                case Cmp_NonZero: Log::out() << "Cmp_NonZero "; break;
                default: assert(0); break;
                }
                src0->print(Log::out());
                Log::out() << ::std::endl;
                Log::out() << "negBranchOperation.hashcode() == "
                           << (int) negBranchOperation.encodeForHashing()
                           << ::std::endl;
                Log::out() << "negCmpOperation.hashcode() == "
                           << (int) negCmpOperation.encodeForHashing()
                           << ::std::endl;
            }

            setHashToInst(getTauUnsafe(), getKey(negBranchOperation, src0->getId()));
            setHashToInst(getTauUnsafe(), getKey(negCmpOperation, src0->getId()));
        }
        break;
    case 2:
        {
            Opnd *posSrc0 = isTrueEdge ? src0 : src1;
            Opnd *posSrc1 = isTrueEdge ? src1 : src0;
            Opnd *negSrc0 = isTrueEdge ? src1 : src0;
            Opnd *negSrc1 = isTrueEdge ? src0 : src1;

            if (Log::isEnabled()) {
                Log::out() << "adding true comparison: ";
                switch (modhere) {
                case Cmp_EQ: Log::out() << "Cmp_EQ "; break;
                case Cmp_NE_Un: Log::out() << "Cmp_NE_Un "; break;
                case Cmp_GT: Log::out() << "Cmp_GT "; break;
                case Cmp_GT_Un: Log::out() << "Cmp_GT_Un "; break;
                case Cmp_GTE: Log::out() << "Cmp_GTE "; break;
                case Cmp_GTE_Un: Log::out() << "Cmp_GTE_Un "; break;
                default: assert(0); break;
                }
                posSrc0->print(Log::out());
                Log::out() << ", ";
                posSrc1->print(Log::out());
                Log::out() << ::std::endl;
            }

            Inst *tauEdge = getBlockTauEdge(targetNode)->getInst();
            setHashToInst(tauEdge, 
                          getKey(branchOperation, posSrc0->getId(), posSrc1->getId()));
            setHashToInst(tauEdge,
                          getKey(cmpOperation, posSrc0->getId(), posSrc1->getId()));

            if (Log::isEnabled()) {
                Log::out() << "adding false comparison: ";
                switch (negModhere) {
                case Cmp_EQ: Log::out() << "Cmp_EQ "; break;
                case Cmp_NE_Un: Log::out() << "Cmp_NE_Un "; break;
                case Cmp_GT: Log::out() << "Cmp_GT "; break;
                case Cmp_GT_Un: Log::out() << "Cmp_GT_Un "; break;
                case Cmp_GTE: Log::out() << "Cmp_GTE "; break;
                case Cmp_GTE_Un: Log::out() << "Cmp_GTE_Un "; break;
                default: assert(0); break;
                }
                posSrc0->print(Log::out());
                Log::out() << ", ";
                posSrc1->print(Log::out());
                Log::out() << ::std::endl;
            }
            
            setHashToInst(getTauUnsafe(),
                          getKey(negBranchOperation, negSrc0->getId(), 
                                 negSrc1->getId()));
            setHashToInst(getTauUnsafe(),
                          getKey(negCmpOperation, negSrc0->getId(), 
                                 negSrc1->getId()));
        }
        break;
    default:
        assert(0);
        break;
    }

    Opnd *opnd = 0;
    Opnd *opnd2 = 0;
    Type *type = 0;
    Inst *tauEdge = 0;
    if (allowsCheckZeroElimination(mod, comparisonType, src0, src1, isTrueEdge, 
                                   &opnd)) {
        assert(opnd);
        if (Log::isEnabled()) {
            Log::out() << "can eliminate checkzero of ";
            opnd->print(Log::out());
            Log::out() << ::std::endl;
        }

        if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
        setHashToInst(tauEdge,
                      getKey(Operation(Op_TauCheckZero, opnd->getType()->tag,
                                       Modifier(Exception_Sometimes)),
                             opnd->getId()));
    }
    if (allowsCheckNullElimination(mod, comparisonType, src0, src1, isTrueEdge, 
                                   &opnd)) {
        bool repeat_it;
        do {
            repeat_it = false;

            assert(opnd);
            if (Log::isEnabled()) {
                Log::out() << "can eliminate checknull of ";
                opnd->print(Log::out());
                Log::out() << ::std::endl;
            }
            if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
            setHashToInst(tauEdge,
                          getKey(Op_TauCheckNull,
                                 opnd->getId()));
            setHashToInst(tauEdge,
                          getKey(Operation(Op_TauIsNonNull,
                                           opnd->getType()->tag,
                                           Modifier()),
                                 opnd->getId()));

            Inst *opndInst = opnd->getInst();
            Opcode opndInstOpcode = opndInst->getOpcode();
            if (opndInstOpcode == Op_TauStaticCast) {
                // if a static cast, source is also non-null
                opnd = opndInst->getSrc(0);
                repeat_it = true;
            }
        } while (repeat_it);
    }
    if (allowsCheckBoundsElimination(mod, comparisonType, src0, src1, isTrueEdge, 
                                     &opnd, &opnd2)) {
        assert(opnd);
        assert(opnd2);
        if (Log::isEnabled()) {
            Log::out() << "can eliminate checkbounds of ";
            opnd->print(Log::out());
            Log::out() << ", ";
            opnd2->print(Log::out());
            Log::out() << ::std::endl;
        }
        if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
        setHashToInst(tauEdge,
                      getKey(Operation(Op_TauCheckBounds, opnd->getType()->tag,
                                       Modifier(Exception_Sometimes)),
                             opnd->getId(), opnd2->getId()));
    }
    if (allowsCheckCastElimination(mod, comparisonType, src0, src1, isTrueEdge,
                                   &opnd, &type)) {
        bool repeat_it;
        do {
            repeat_it = false;
            assert(opnd);
            assert(type);
            if (Log::isEnabled()) {
                Log::out() << "can eliminate checkcast of ";
                opnd->print(Log::out());
                Log::out() << ", ";
                type->print(Log::out());
                Log::out() << ::std::endl;
            }
            if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
            opnd2 = irManager.getOpndManager().createSsaTmpOpnd(type);
            Inst* scast = irManager.getInstFactory().makeTauStaticCast(opnd2, opnd,
                                                                       tauEdge->getDst(), type);
            if(Log::isEnabled()) {
                Log::out() << "Inserting staticCast inst ";
                scast->print(Log::out());
                Log::out() << " after tauEdge ";
                tauEdge->print(Log::out());
                Log::out() << ::std::endl;
            }
            scast->insertAfter(tauEdge);

            if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
            // make checks available
            recordHasTypeTau(opnd, type, tauEdge);

            Inst *opndInst = opnd->getInst();
            Opcode opndInstOpcode = opndInst->getOpcode();
            if (opndInstOpcode == Op_TauStaticCast) {
                // if a static cast, source is also in the type
                opnd = opndInst->getSrc(0);
                repeat_it = true;
            }
        } while (repeat_it);
    }
    if (allowsCheckElemTypeElimination(mod, comparisonType, src0, src1, 
                                       isTrueEdge,
                                       &opnd, &opnd2)) {
        bool repeat_it;
        do {
            repeat_it = false;
            assert(opnd);
            assert(opnd2);
            if (Log::isEnabled()) {
                Log::out() << "can eliminate checkelemtype of ";
                opnd->print(Log::out());
                Log::out() << ", ";
                opnd2->print(Log::out());
                Log::out() << ::std::endl;
            }
            if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
            setHashToInst(tauEdge,
                          getKey(Operation(Op_TauCheckElemType, 
                                           opnd->getType()->tag, 
                                           (Modifier(Exception_Sometimes))),
                                 opnd->getId(), 
                                 opnd2->getId()));

            Inst *opndInst = opnd->getInst();
            Opcode opndInstOpcode = opndInst->getOpcode();
            if (opndInstOpcode == Op_TauStaticCast) {
                // if a static cast, source is also in the type
                opnd = opndInst->getSrc(0);
                repeat_it = true;
            }
        } while (repeat_it);
    }
    if (allowsConstantPropagation(mod, comparisonType, src0, src1, isTrueEdge,
                                  &opnd, &opnd2)) {
        bool repeat_it;
        do {
            repeat_it = false;

            // opnd2 is a constant expression
            if (constantTable)
                constantTable->insert(opnd, opnd2);
            
            // vtable comparison guarantees type safety
            if (Type::isVTablePtr(comparisonType)) {
                Inst *opnd2inst = opnd2->getInst();
                assert(opnd2inst->getOpcode() == Op_GetVTableAddr);
                Inst *opnd1inst = opnd->getInst();
                if (opnd1inst->getOpcode() == Op_TauLdVTableAddr) {
                    TypeInst *opnd2typeInst = opnd2inst->asTypeInst();
                    Opnd *base = opnd1inst->getSrc(0);
                    if (!tauEdge) tauEdge = getBlockTauEdge(targetNode)->getInst();
                    Type *typeInfo = opnd2typeInst->getTypeInfo();
                    setHashToInst(tauEdge,
                                  getKey(Op_TauHasExactType,
                                         base->getId(),
                                         opnd2typeInst->getType()));
                    recordHasTypeTau(base, typeInfo, tauEdge);
                }
            }

            Inst *opndInst = opnd->getInst();
            Opcode opndInstOpcode = opndInst->getOpcode();
            if (opndInstOpcode == Op_TauStaticCast) {
                // if a static cast, source is also the constant
                opnd = opndInst->getSrc(0);
                repeat_it = true;
            }
        } while (repeat_it);
    }        
}