Exemple #1
0
Opnd* OpndUtils::getZeroConst(Type* type)
{
    if (type->isDouble()) {
        return getDoubleZeroConst();
    }
    if (type->isSingle()) {
        return getFloatZeroConst();
    }
    if (type->isInt4()) {
        return getIntZeroConst();
    }
    return m_irManager->newImmOpnd(type, 0);
}
PeepHoleOpt::Changed PeepHoleOpt::handleInst_Convert_F2I_D2I(Inst* inst)
{
    //
    // Inline 'int_value = (int)(float_value or double_value)'
    //
    Opnd* dst = inst->getOpnd(0);
    Opnd* src = inst->getOpnd(2);
    Type* srcType = src->getType();
    assert(srcType->isSingle() || srcType->isDouble());
    assert(dst->getType()->isInt4());
    const bool is_dbl = srcType->isDouble();
    // Here, we might have to deal with 3 cases with src (_value):
    // 1. Unassigned operand - act as if were operating with XMM
    // 2. Assigned to FPU - convert to FPU operations, to 
    //    avoid long FPU->mem->XMM chain
    // 3. Assigned to XMM - see #1
    const bool xmm_way = 
        !(src->hasAssignedPhysicalLocation() && src->isPlacedIn(OpndKind_FPReg));

    if (!xmm_way) {
        //TODO: will add FPU later if measurements show it worths trying
        return Changed_Nothing;
    }
    //
    //
    /*
        movss xmm0, val
        // presuming the corner cases (NaN, overflow) 
        // normally happen rare, do conversion first, 
        // and check for falls later
    -- convertNode
        cvttss2si eax, xmm0
    -- ovfTestNode
        // did overflow happen ?
        cmp eax, 0x80000000 
        jne _done               // no - go return result
    -- testAgainstZeroNode
        // test SRC against zero
        comiss xmm0, [fp_zero]
        // isNaN ? 
        jp _nan     // yes - go load 0
    -- testIfBelowNode
        // xmm < 0 ?
        jb _done    // yes - go load MIN_INT. EAX already has it - simply return.
    -- loadMaxIntNode 
        // ok. at this point, XMM is positive and > MAX_INT
        // must load MAX_INT which is 0x7fffffff.
        // As EAX has 0x80000000, then simply substract 1
        sub eax, 1
        jmp _done
    -- loadZeroNode
    _nan:
        xor eax, eax
    -- nodeNode
    _done:
        mov result, eax
    }
    */
    Opnd* fpZeroOpnd = getZeroConst(srcType);
    Type* int32type = irManager->getTypeManager().getInt32Type();
    Opnd* oneOpnd = irManager->newImmOpnd(int32type, 1);
    Opnd* intZeroOpnd = getIntZeroConst();

    // 0x8..0 here is not the INT_MIN, but comes from the COMISS 
    // opcode description instead.
    Opnd* minIntOpnd = irManager->newImmOpnd(int32type, 0x80000000);

    newSubGFG();
    Node* entryNode = getSubCfgEntryNode();

    Node* convertNode = newBB();
    Node* ovfTestNode = newBB();
    Node* testAgainstZeroNode = newBB();
    Node* testIfBelowNode = newBB();
    Node* loadMaxIntNode = newBB();
    Node* loadZeroNode = newBB();
    Node* doneNode = newBB();
    //
    // presuming the corner cases (NaN, overflow) 
    // normally happen rare, do conversion first, 
    // and check for falls later
    //
    connectNodes(entryNode, convertNode);
    //
    // convert
    //
    setCurrentNode(convertNode)    ;
    Mnemonic mn_cvt = is_dbl ? Mnemonic_CVTTSD2SI : Mnemonic_CVTTSS2SI;
    /*cvttss2si r32, xmm*/ newInst(mn_cvt, 1, dst, src);
    connectNodeTo(ovfTestNode);
    setCurrentNode(NULL);

    //
    // check whether overflow happened
    //
    setCurrentNode(ovfTestNode);
    /*cmp r32, MIN_INT*/ newInst(Mnemonic_CMP, dst, minIntOpnd);
    /*jne _done       */ newBranch(Mnemonic_JNE, doneNode, testAgainstZeroNode, 0.9, 0.1);
    //
    setCurrentNode(NULL);

    // test SRC against zero
    //
    setCurrentNode(testAgainstZeroNode);
    Mnemonic mn_cmp = is_dbl ? Mnemonic_UCOMISD : Mnemonic_UCOMISS;
    /*comiss src, 0.  */ newInst(mn_cmp, src, fpZeroOpnd);
    /*jp _nan:result=0*/ newBranch(Mnemonic_JP, loadZeroNode, testIfBelowNode);
    setCurrentNode(NULL);

    //
    // 
    //
    setCurrentNode(loadZeroNode);
    /*mov r32, 0*/      newInst(Mnemonic_MOV, dst, intZeroOpnd);
    /*jmp _done*/       connectNodeTo(doneNode);
    setCurrentNode(NULL);

    //
    // test if we have a huge negative in SRC
    //
    setCurrentNode(testIfBelowNode);
    /*jb _done:*/       newBranch(Mnemonic_JB, doneNode, loadMaxIntNode);
    setCurrentNode(NULL);
    //
    // 
    //
    setCurrentNode(loadMaxIntNode);
    /* sub dst, 1*/     newInst(Mnemonic_SUB, dst, oneOpnd);
    connectNodeTo(doneNode);
    setCurrentNode(NULL);
    //
    connectNodes(doneNode, getSubCfgReturnNode());
    //
    propagateSubCFG(inst);
    return Changed_Node;
}