void InsertPi::insertPiForComparison()

in vm/jitrino/src/optimizer/abcd/insertpi.cpp [410:689]


void InsertPi::insertPiForComparison(Node* block,
                                     ComparisonModifier mod,
                                     const PiCondition &bounds,
                                     Opnd* op,
                                     bool swap_operands,
                                     bool negate_comparison)
{
    if (Log::isEnabled()) {
        Log::out() << "insertPiForComparison(..., ";
        Log::out() << printableComparison(mod);
        Log::out() << ", ";
        bounds.print(Log::out());
        Log::out() << ", ";
        op->print(Log::out());
        Log::out() << ", ";
        Log::out() << (swap_operands ? "true" : "false");
        Log::out() << ", ";
        Log::out() << (negate_comparison ? "true" : "false");
        Log::out() << ")" << std::endl;

        // Print last inst from all prev blocks.
        Edges::const_iterator it = block->getInEdges().begin(),
            end = block->getInEdges().end();
        for(; it != end; ++it) {
            Edge* edge = (*it);
            Log::out() << "pred inst---> ";
            ((Inst*)edge->getSourceNode()->getLastInst())->print(Log::out());
            Log::out() << std::endl;
        }
    }

    PiCondition bounds0 = bounds;
    // add a Pi node for immediate value.
    if (negate_comparison) {
        mod = negateComparison(mod);
        swap_operands = !swap_operands;
        if (Log::isEnabled()) {
            Log::out() << "insertPiForComparison: negating comparison to " ;
            Log::out() << printableComparison(mod);
            Log::out() << std::endl;
        }
    }
    switch (mod) {
    case Cmp_EQ:
        if (!negate_comparison)
            insertPiForOpndAndAliases(block, op, bounds0, NULL);
        else {
            if (Log::isEnabled()) {
                Log::out() << "insertPiForComparison: cannot represent ! Cmp_EQ" << std::endl;
            }
        }
        // we can't represent the other case
        break;
    case Cmp_NE_Un:
        if (negate_comparison)
            insertPiForOpndAndAliases(block, op, bounds0, NULL);
        else {
            if (Log::isEnabled()) {
                Log::out() << "insertPiForComparison: cannot represent Cmp_NE_Un" << std::endl;
            }
        }
        // we can't represent the other case
        break;
    case Cmp_GT_Un:
        if (swap_operands) { // op > bounds, only a lower bound on op
            Type::Tag optag = op->getType()->tag;
            if (!Type::isUnsignedInteger(optag)) {
                // 1 is a lower bound on int op
                PiCondition oneBounds(PiBound(optag, (int64)1), 
                                      PiBound(optag, (int64)1));
                PiCondition oneLowerBound(oneBounds.only_lower_bound());
                insertPiForOpndAndAliases(block, op, oneLowerBound, NULL);
            } else {
                // we can be more precise for an unsigned op
                bounds0 = bounds0.cast(unsignType(bounds0.getType()));
                PiCondition bounds1a(bounds0.only_lower_bound());
                PiCondition bounds1(bounds1a.add((int64)1));
                if (! bounds1.getLb().isUnknown())
                    insertPiForOpndAndAliases(block, op, bounds1, NULL);
                else {
                    if (Log::isEnabled()) {
                        Log::out() << "insertPiForComparison(1): bounds1 LB is Unknown;\n\tbounds is ";
                        bounds.print(Log::out());
                        Log::out() << "\n\tbounds0 is ";
                        bounds0.print(Log::out());
                        Log::out() << "\n\tbounds1a is ";
                        bounds1a.print(Log::out());
                        Log::out() << "\n\tbounds1 is ";
                        bounds1.print(Log::out());
                        Log::out() << std::endl;
                    }
                }
            }
        } else { // bounds > op, only an upper bound on op
            Type::Tag optag = op->getType()->tag;
            if (Type::isUnsignedInteger(optag)) {
                // for an unsigned upper bound, we're ok
                bounds0 = bounds0.cast(unsignType(bounds0.getType()));
                PiCondition bounds1(bounds0.only_upper_bound().add((int64)-1));
                if (! bounds1.getUb().isUnknown())
                    insertPiForOpndAndAliases(block, op, bounds1, NULL);
                else {
                    if (Log::isEnabled()) {
                        Log::out() << "insertPiForComparison(2): bounds1 LB is Unknown;\n\tbounds is ";
                        bounds.print(Log::out());
                        Log::out() << "\n\tbounds0 is ";
                        bounds0.print(Log::out());
                        Log::out() << "\n\tbounds1 is ";
                        bounds1.print(Log::out());
                        Log::out() << std::endl;
                    }
                }
            } else {
                // otherwise, we know nothing unless bound is a small constant
                PiCondition bounds1(bounds0.only_upper_bound().add((int64)-1));
                if (bounds0.getUb().isConstant()) {
                    int64 ubConst = bounds1.getUb().getConst();
                    if (((optag == Type::Int32) &&
                         ((ubConst&0xffffffff) <= 0x7ffffff) && 
                         ((ubConst&0xffffffff) >= 0)) ||
                        ((optag == Type::Int64) &&
                         ((ubConst <= 0x7ffffff) && 
                          (ubConst >= 0)))) {
                        insertPiForOpndAndAliases(block, op, bounds1, NULL);
                    } else {
                        if (Log::isEnabled()) {
                            Log::out() << "insertPiForComparison(2): bounds1 LB is Unknown;\n\tbounds is ";
                            bounds.print(Log::out());
                            Log::out() << "\n\tbounds0 is ";
                            bounds0.print(Log::out());
                            Log::out() << "\n\tbounds1 is ";
                            bounds1.print(Log::out());
                            Log::out() << std::endl;
                        }
                    }
                }
            }
        }
        break;
    case Cmp_GT:
        if (swap_operands) { // op > bounds, only a lower bound on op
            PiCondition bounds1a(bounds0.only_lower_bound());
            PiCondition bounds1(bounds1a.add((int64)1));
            if (! bounds1.getLb().isUnknown())
                insertPiForOpndAndAliases(block, op, bounds1, NULL);
            else {
                if (Log::isEnabled()) {
                    Log::out() << "insertPiForComparison(1): bounds1 LB is Unknown;\n\tbounds is ";
                    bounds.print(Log::out());
                    Log::out() << "\n\tbounds0 is ";
                    bounds0.print(Log::out());
                    Log::out() << "\n\tbounds1a is ";
                    bounds1a.print(Log::out());
                    Log::out() << "\n\tbounds1 is ";
                    bounds1.print(Log::out());
                    Log::out() << std::endl;
                }
            }
        } else { // bounds > op, only an upper bound on op
            PiCondition bounds1(bounds0.only_upper_bound().add((int64)-1));
            if (! bounds1.getUb().isUnknown())
                insertPiForOpndAndAliases(block, op, bounds1, NULL);
            else {
                if (Log::isEnabled()) {
                    Log::out() << "insertPiForComparison(2): bounds1 LB is Unknown;\n\tbounds is ";
                    bounds.print(Log::out());
                    Log::out() << "\n\tbounds0 is ";
                    bounds0.print(Log::out());
                    Log::out() << "\n\tbounds1 is ";
                    bounds1.print(Log::out());
                    Log::out() << std::endl;
                }
            }
        }
        break;
    case Cmp_GTE_Un:
        if (swap_operands) { // op >= bounds, only lower bound on op
            Type::Tag optag = op->getType()->tag;
            if (!Type::isUnsignedInteger(optag)) {
                // 0 is a lower bound on an int op
                PiCondition zeroBounds(PiBound(optag, (int64)0), 
                                       PiBound(optag, (int64)0));
                PiCondition zeroLowerBound(zeroBounds.only_lower_bound());
                insertPiForOpndAndAliases(block, op, zeroLowerBound, NULL);
            } else {
                // we can be more precise for an unsigned op lb
                bounds0 = bounds0.cast(unsignType(bounds0.getType()));
                if (! bounds0.getLb().isUnknown()) {
                    insertPiForOpndAndAliases(block, op, 
                                                  bounds0.only_lower_bound(), NULL);
                } else {
                    if (Log::isEnabled()) {
                        Log::out() << "insertPiForComparison(3): bounds0 LB is Unknown;\n\tbounds is ";
                        bounds.print(Log::out());
                        Log::out() << "\n\tbounds0 is ";
                        bounds0.print(Log::out());
                        Log::out() << std::endl;
                    }
                }
            }
        } else { // bounds >= op, only upper bound on op
            Type::Tag optag = op->getType()->tag;
            if (Type::isUnsignedInteger(optag)) {
                // unsigned ub on unsigned op 
                bounds0 = bounds0.cast(unsignType(bounds0.getType()));
                if (! bounds0.getUb().isUnknown())
                    insertPiForOpndAndAliases(block, op, 
                                                  bounds0.only_upper_bound(), NULL);
                else {
                    if (Log::isEnabled()) {
                        Log::out() << "insertPiForComparison(4): bounds0 UB is Unknown;\n\tbounds is ";
                        bounds.print(Log::out());
                        Log::out() << "\n\tbounds0 is ";
                        bounds0.print(Log::out());
                        Log::out() << std::endl;
                    }
                }
            } else {
                // otherwise, we know nothing unless bound is a small constant
                if (bounds0.getUb().isConstant()) {
                    int64 ubConst = bounds0.getUb().getConst();
                    if (((optag == Type::Int32) &&
                         ((ubConst&0xffffffff) <= 0x7ffffff) && 
                         ((ubConst&0xffffffff) >= 0)) ||
                        ((optag == Type::Int64) &&
                         ((ubConst <= 0x7ffffff) && 
                          (ubConst >= 0)))) {
                        insertPiForOpndAndAliases(block, op, bounds0, NULL);
                    } else {
                        if (Log::isEnabled()) {
                            Log::out() << "insertPiForComparison(2): bounds0 LB is Unknown;\n\tbounds is ";
                            bounds.print(Log::out());
                            Log::out() << "\n\tbounds0 is ";
                            bounds0.print(Log::out());
                            Log::out() << std::endl;
                        }
                    }
                }
            }
        }
        break;
    case Cmp_GTE:
        if (swap_operands) { // op >= bounds, only lower bound on op
            if (! bounds0.getLb().isUnknown()) {
                insertPiForOpndAndAliases(block, op, 
                                              bounds0.only_lower_bound(), NULL);
            } else {
                if (Log::isEnabled()) {
                    Log::out() << "insertPiForComparison(3): bounds0 LB is Unknown;\n\tbounds is ";
                    bounds.print(Log::out());
                    Log::out() << "\n\tbounds0 is ";
                    bounds0.print(Log::out());
                    Log::out() << std::endl;
                }
            }
        } else { // bounds >= op, only upper bound on op
            if (! bounds0.getUb().isUnknown())
                insertPiForOpndAndAliases(block, op, 
                                              bounds0.only_upper_bound(), NULL);
            else {
                if (Log::isEnabled()) {
                    Log::out() << "insertPiForComparison(4): bounds0 UB is Unknown;\n\tbounds is ";
                    bounds.print(Log::out());
                    Log::out() << "\n\tbounds0 is ";
                    bounds0.print(Log::out());
                    Log::out() << std::endl;
                }
            }
        }
        break;
    case Cmp_Zero:
    case Cmp_NonZero:
    case Cmp_Mask:
        assert(0);
        break;
    default:
    assert(false);
    break;
    }
}