Esempio n. 1
0
void Opnd::normalizeMemSubOpnds(void)
{
    if (!isPlacedIn(OpndKind_Mem)) {
        return;
    }
    Opnd* base = getMemOpndSubOpnd(MemOpndSubOpndKind_Base);
    Opnd* disp = getMemOpndSubOpnd(MemOpndSubOpndKind_Displacement);
    if (base != NULL && base->isPlacedIn(OpndKind_Imm)) {
        assert(disp == NULL || !disp->isPlacedIn(OpndKind_Imm) || base->getType()->isNullObject());
        setMemOpndSubOpnd(MemOpndSubOpndKind_Displacement, base);
        // can't call setMemOpndSubOpnd() as it fights against zero opnd.
        memOpndSubOpnds[MemOpndSubOpndKind_Base] = disp; //==setMemOpndSubOpnd(MemOpndSubOpndKind_Base, disp);
    }
}
Esempio n. 2
0
//_________________________________________________________________________________________________
void DCE::runImpl()
{
    bool early = false;
    getArg("early", early);
    if (early && !irManager->getCGFlags()->earlyDCEOn) {
        return;
    }

    irManager->updateLivenessInfo();
    irManager->calculateOpndStatistics();
    BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
    const Nodes& nodes = irManager->getFlowGraph()->getNodesPostOrder();

#ifdef ORDER

    MemoryManager mm("dce_parents");

    U_32 opndCount = irManager->getOpndCount();
    bool * isParentOpnd = new(mm) bool [opndCount];
    memset(isParentOpnd, 0, sizeof(bool) * opndCount);
    for (Nodes::const_iterator it = nodes.begin(),end = nodes.end(); it!=end; ++it) {
        Node* node = *it;
        for (Inst * inst=(Inst*)node->getLastInst(); inst!=NULL; inst=inst->getPrevInst()) {
            Opnd* load_obj = inst->getParentObjectLoad();
            if (load_obj)
            {
                isParentOpnd[load_obj->getId()] = true;
            }

            Opnd* store_obj = inst->getParentObjectStore();
            if (store_obj)
            {
                isParentOpnd[store_obj->getId()] = true;
            }

        }
    }
#endif



    for (Nodes::const_iterator it = nodes.begin(),end = nodes.end(); it!=end; ++it) {
        Node* node = *it;
        if (node->isBlockNode()) {
            //Here we'll try to remove redundant branches that could appear after
            //branch translations. All such branches are supposed to be conditional.
            Inst * inst = (Inst *)node->getLastInst();
            if(inst && node->getOutEdges().size() > 1) {
                Edges edges = node->getOutEdges();
                for (Edges::const_iterator ite1 = ++edges.begin(), end = edges.end(); ite1 != end; ++ite1) {
                    for (Edges::const_iterator ite2 = edges.begin(); ite1 != ite2; ++ite2) {
                        Edge *edge1 = *ite1;
                        Edge *edge2 = *ite2;
                        assert(edge1 != edge2);

                        //If this condition is satisfied then there are at least two branches with
                        //the same destination
                        if (edge1->getTargetNode() == edge2->getTargetNode()) {
                            //Check that edges are conditional and the last instruction is branch,
                            //the other situations are not permitted at the moment
                            assert(inst->hasKind(Inst::Kind_BranchInst));
                            assert(edge1->getKind() == Edge::Kind_True ||
                                   edge1->getKind() == Edge::Kind_False);
                            assert(edge2->getKind() == Edge::Kind_True ||
                                   edge2->getKind() == Edge::Kind_False);

                            //Remove last instruction if it is a branch
                            inst->unlink();
                            irManager->getFlowGraph()->removeEdge(edge2);
                        }

                    }
                }
            }

            irManager->getLiveAtExit(node, ls);
            for (Inst * inst=(Inst*)node->getLastInst(), * prevInst=NULL; inst!=NULL; inst=prevInst) {
                prevInst=inst->getPrevInst();
                // Prevent debug traps or instructions with side effects
                // like (MOVS) from being removed.
                bool deadInst=!inst->hasSideEffect() && (inst->getMnemonic() != Mnemonic_INT3);

#ifdef ORDER //yzm
                for (unsigned int i = 0 ; i < inst->getOpndCount() ; i ++)
                {
                    Opnd* opnd = inst->getOpnd(i);
                    if (isParentOpnd[opnd->getId()])
                        deadInst = false;
                }
#endif

                if (deadInst) {
                    if (inst->hasKind(Inst::Kind_CopyPseudoInst)) {
                        Opnd * opnd=inst->getOpnd(1);
                        if (opnd->getType()->isFP() && opnd->getDefiningInst()!=NULL && opnd->getDefiningInst()->getMnemonic()==Mnemonic_CALL) {
                            deadInst=false;
                        }
                    }
                    if (deadInst) {
                        Inst::Opnds opnds(inst, Inst::OpndRole_All);
                        for (Inst::Opnds::iterator ito = opnds.begin(); ito != opnds.end(); ito = opnds.next(ito)) {
                            Opnd * opnd = inst->getOpnd(ito);
                            if ((ls.getBit(opnd->getId()) && (inst->getOpndRoles(ito) & Inst::OpndRole_Def)) ||
                                    (((opnd->getMemOpndKind()&(MemOpndKind_Heap|MemOpndKind_StackManualLayout))!=0) && (inst->getMnemonic() != Mnemonic_LEA))) {
                                deadInst=false;
                                break;
                            }
                        }
                    }
                }
                if (deadInst) {
                    inst->unlink();
                } else {
                    irManager->updateLiveness(inst, ls);
                }
            }
            irManager->getLiveAtEntry(node)->copyFrom(ls);
        }
    }

    irManager->eliminateSameOpndMoves();

    irManager->getFlowGraph()->purgeEmptyNodes();
    irManager->getFlowGraph()->mergeAdjacentNodes(true, false);
    irManager->getFlowGraph()->purgeUnreachableNodes();

    irManager->packOpnds();
    irManager->invalidateLivenessInfo();
}
//___________________________________________________________________________________________________
void EarlyPropagation::runImpl()
{ 
        irManager->updateLoopInfo();
        U_32 opndCount=irManager->getOpndCount();

        MemoryManager mm("early_prop");
        OpndInfo * opndInfos = new(mm) OpndInfo[opndCount];
        Node * currentLoopHeader = NULL;

        bool anyInstHandled=false;

        LoopTree* lt = irManager->getFlowGraph()->getLoopTree();
        const Nodes& postOrdered = irManager->getFlowGraph()->getNodesPostOrder();
        for (Nodes::const_reverse_iterator it = postOrdered.rbegin(), end = postOrdered.rend(); it!=end; ++it) {
            Node * node=*it;
            if (!node->isBlockNode())  {
                continue;
            }
            Node * loopHeader = lt->getLoopHeader(node, false);
            if (currentLoopHeader != loopHeader){
                currentLoopHeader = loopHeader;
                for (U_32 i = 0; i < opndCount; ++i)
                    if (opndInfos[i].sourceOpndId != EmptyUint32)
                        opndInfos[i].defCount++;
            }

            for (Inst * inst = (Inst*)node->getFirstInst(); inst != NULL; inst=inst->getNextInst()){
                bool assignedOpndPropagated = false;
                Inst::Opnds opnds(inst, Inst::OpndRole_All);
                for (Inst::Opnds::iterator it = opnds.begin(); it != opnds.end(); it = opnds.next(it)){
                    Opnd * opnd=inst->getOpnd(it);
                    U_32 roles=inst->getOpndRoles(it);
                    U_32 opndId = opnd->getId();
                    OpndInfo& opndInfo = opndInfos[opndId];

                    U_32 mask = 0;

                    if (roles & Inst::OpndRole_Def){
                        ++opndInfo.defCount;
                    }else if (roles & Inst::OpndRole_Use){
                        if (opndInfo.sourceOpndId != EmptyUint32){
                            if (opndInfo.sourceOpndDefCountAtCopy < opndInfos[opndInfo.sourceOpndId].defCount)
                                opndInfo.sourceOpndId = EmptyUint32;
                            else{
                                Opnd * srcOpnd = irManager->getOpnd(opndInfo.sourceOpndId);
                                Constraint co = srcOpnd->getConstraint(Opnd::ConstraintKind_Location);
                                if (co.getKind() == OpndKind_Mem){
                                    mask = (1<<it)-1;
                                    if ((roles & Inst::OpndRole_Explicit) == 0 ||
                                        inst->hasKind(Inst::Kind_PseudoInst) || irManager->isGCSafePoint(inst) ||
                                        opndInfo.sourceInst != inst->getPrevInst() || assignedOpndPropagated ||
                                    (inst->getConstraint(it, mask, co.getSize())&co).isNull()
                                    )
                                        opndInfo.sourceOpndId = EmptyUint32;
                                    assignedOpndPropagated = true;
                                }
                            }
                        }
                    }
                    if (opndInfo.defCount > 1){
                        opndInfo.sourceOpndId = EmptyUint32;
                    }
                }
                /*
                Here is the previous version to test whether the inst is copy or not.
                bool isCopy = inst->getMnemonic() == Mnemonic_MOV ||(
                        (inst->getMnemonic() == Mnemonic_ADD || inst->getMnemonic() == Mnemonic_SUB) && 
                        inst->getOpnd(3)->isPlacedIn(OpndKind_Imm) && inst->getOpnd(3)->getImmValue()==0
                        && inst->getOpnd(3)->getRuntimeInfo()==NULL
                    );
                It considered special case of 'dst = src +/- 0' as copy. 
                In fact there are more similar cases like 'IMUL src, 1 ; shift src, 0' etc.
                Such checks are obsolete now, Should as peephole takes care about such copies.

                Anyway, the code above had a bug: 'inst->getOpnd(3)' crashes in instructions 
                in native form (like ADD def_use, use).
                */
                const bool isCopy = inst->getMnemonic() == Mnemonic_MOV;

                if (isCopy){ // CopyPseudoInst or mov
                    Opnd * defOpnd = inst->getOpnd(0);
                    Opnd * srcOpnd = inst->getOpnd(1);
                    U_32 defOpndId = defOpnd->getId();
                    OpndInfo * opndInfo = opndInfos + defOpndId;
                    bool instHandled=false;
                    bool typeConvOk = isTypeConversionAllowed(srcOpnd, defOpnd);
                    if (typeConvOk && opndInfo->defCount == 1 && ! srcOpnd->isPlacedIn(OpndKind_Reg)){
                        if (!defOpnd->hasAssignedPhysicalLocation()){
                            opndInfo->sourceInst = inst;
                            opndInfo->sourceOpndId = srcOpnd->getId();
                            instHandled=true;
                        }
                    }
                    if (instHandled){
                        if (opndInfos[opndInfo->sourceOpndId].sourceOpndId != EmptyUint32)
                            opndInfo->sourceOpndId = opndInfos[opndInfo->sourceOpndId].sourceOpndId;
                        opndInfo->sourceOpndDefCountAtCopy = opndInfos[opndInfo->sourceOpndId].defCount;
                        anyInstHandled=true;
                    }
                }
            }
        }

        if (anyInstHandled){
            Opnd ** replacements = new(mm) Opnd* [opndCount];
            memset(replacements, 0, sizeof(Opnd*) * opndCount);
            bool hasReplacements = false;
            for (U_32 i = 0; i < opndCount; ++i){
                if (opndInfos[i].sourceOpndId != EmptyUint32){
                    Inst * inst = opndInfos[i].sourceInst;
                    if (inst !=NULL){
                        inst->unlink();
                    }
                    if (opndInfos[i].sourceOpndId != i){
                        Opnd* origOpnd= irManager->getOpnd(i);
                        Opnd* replacementOpnd = irManager->getOpnd(opndInfos[i].sourceOpndId);
                        assert(isTypeConversionAllowed(replacementOpnd, origOpnd));
                        if (origOpnd->getType()->isUnmanagedPtr() && replacementOpnd->getType()->isInteger()) {
                            replacementOpnd->setType(origOpnd->getType());
                        }/* else if (origOpnd->getType()->isObject() && replacementOpnd->getType()->isUnmanagedPtr()) {
                            replacementOpnd->setType(origOpnd->getType());
                        }*/
                        replacements[i] = replacementOpnd;
                        hasReplacements = true;
                    }
                }
            }

            if (hasReplacements){
                const Nodes& postOrdered = irManager->getFlowGraph()->getNodesPostOrder();
                for (Nodes::const_reverse_iterator it = postOrdered.rbegin(), end = postOrdered.rend(); it!=end; ++it) {
                    Node * node=*it;
                    if (!node->isBlockNode())  {
                        continue;
                    }
                    for (Inst * inst = (Inst*)node->getFirstInst(); inst != NULL; inst=inst->getNextInst()){
                        inst->replaceOpnds(replacements);
                    }   
                }
            }
        }
}
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;
}