//___________________________________________________________________________________________________
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);
                    }   
                }
            }
        }
}
Ejemplo n.º 2
0
PeepHoleOpt::Changed PeepHoleOpt::handleInst(Inst* inst)
{
    PeepHoleOpt::Changed temp;

    // Local propagation
    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);
                
        if (roles & Inst::OpndRole_Use) {
            if ((roles & Inst::OpndRole_All & Inst::OpndRole_FromEncoder) 
                && (roles & Inst::OpndRole_All & Inst::OpndRole_ForIterator)
                && (roles & Inst::OpndRole_Changeable) && ((roles & Inst::OpndRole_Def) == 0)
                && copyMap->has(opnd)) {
                if (opnd->getType()->isUnmanagedPtr() && (*copyMap)[opnd]->getType()->isInteger())
                    (*copyMap)[opnd]->setType(opnd->getType());
                inst->setOpnd(it, (*copyMap)[opnd]);
            }
        }
    }

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

        if (roles & Inst::OpndRole_Def) {
            if (copyMap->has(opnd)) {
            	if (Log::isEnabled()) Log::out()<<"copy relation DELETED: " << opnd->getFirstId() << "<=" << (*copyMap)[opnd]->getFirstId() <<std::endl;
                copyMap->erase(opnd);
            }

            tempSet->clear();
            for(StlHashMap<Opnd*, Opnd*>::iterator iter=copyMap->begin();
                iter!=copyMap->end();++iter)
                if (iter->second == opnd) {
                    if (Log::isEnabled()) Log::out()<<"copy relation DELETED: " << iter->first->getFirstId() << "<=" << iter->second->getFirstId() <<std::endl;
                    tempSet->insert(iter->first);
                }
            for(StlSet<Opnd*>::iterator iter=tempSet->begin();
                iter!=tempSet->end();++iter)
                copyMap->erase(*iter);
        }
    }

    if (inst->getMnemonic() == Mnemonic_MOV) {
        Inst::Opnds opnds(inst, Inst::OpndRole_All);
        Opnd * dst = NULL;
        Opnd * src = NULL;
        U_32 counterDef = 0;
        U_32 counterUse = 0;

        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);
                    
            if (roles & Inst::OpndRole_Def) {
                counterDef++;
                dst = opnd;
            } else if (roles & Inst::OpndRole_Use) {
                counterUse++;
                src = opnd;
            }
        }

        if ((counterDef == 1) && (counterUse == 1) && (!dst->hasAssignedPhysicalLocation())) {
            bool kindsAreOk = true;
            if(src->canBePlacedIn(OpndKind_FPReg) || dst->canBePlacedIn(OpndKind_FPReg)) {
                Constraint srcConstr = src->getConstraint(Opnd::ConstraintKind_Calculated);
                Constraint dstConstr = dst->getConstraint(Opnd::ConstraintKind_Calculated);
                kindsAreOk = ! (srcConstr&dstConstr).isNull();
            }
            bool typeConvOk = src->getSize() == dst->getSize() && isTypeConversionAllowed(src, dst);
            if (typeConvOk && kindsAreOk && ! src->isPlacedIn(OpndKind_Reg)) {
                if (copyMap->has(src)) {
                    (*copyMap)[dst] = (*copyMap)[src];
                    if (Log::isEnabled()) Log::out()<<"copy relation INSERTED: " << dst->getFirstId() << "<=" << (*copyMap)[src]->getFirstId() <<std::endl;
                } else {
                    (*copyMap)[dst] = src;
                    if (Log::isEnabled()) Log::out()<<"copy relation INSERTED: " << dst->getFirstId() << "<=" << src->getFirstId() <<std::endl;
                }
            }
        }
    }
            
    if (inst->hasKind(Inst::Kind_PseudoInst) && inst->getKind() != Inst::Kind_CopyPseudoInst) {
        return Changed_Nothing;
    }

    Mnemonic mnemonic = inst->getMnemonic();
    switch(mnemonic) {
    case Mnemonic_MOV:
        return handleInst_MOV(inst);
    case Mnemonic_CALL:
        return handleInst_Call(inst);
    case Mnemonic_ADD:
    case Mnemonic_ADC:
    case Mnemonic_SUB:
    case Mnemonic_SBB:
    case Mnemonic_NOT:
    case Mnemonic_AND:
    case Mnemonic_OR:
    case Mnemonic_XOR:
    case Mnemonic_TEST:
        return handleInst_ALU(inst);
    case Mnemonic_CMP:
    temp = handleInst_CMP(inst);
    if ( temp == Changed_Nothing ) {
        return handleInst_ALU(inst); 
    } else {
        return temp;
    }
    case Mnemonic_SETG:
    case Mnemonic_SETE:
    case Mnemonic_SETNE:
    case Mnemonic_SETL:
		return handleInst_SETcc(inst);
    case Mnemonic_IMUL:
    case Mnemonic_MUL:
        return handleInst_MUL(inst);
    case Mnemonic_MOVSS:
    case Mnemonic_MOVSD:
        //return handleInst_SSEMov(inst);
    case Mnemonic_XORPS:
    case Mnemonic_XORPD:
        //return handleInst_SSEXor(inst);
    default:
        break;
    }
    return Changed_Nothing;
}