Index: working_vm/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp =================================================================== --- working_vm/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp £¨ÐÞ¶©°æ 707991£© +++ working_vm/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp £¨¹¤×÷¿½±´£© @@ -102,7 +102,7 @@ }; // ~PeepHoleOpt void PeepHoleOpt::runImpl(void) -{ +{ setIRManager(irManager); irManager->calculateOpndStatistics(); m_bHadAnyChange = false; @@ -139,6 +139,7 @@ keepGoing = false; } } while(keepGoing); + } @@ -628,19 +629,32 @@ PeepHoleOpt::Changed PeepHoleOpt::handleInst_MUL(Inst* inst) { - assert(inst->getMnemonic()==Mnemonic_IMUL || inst->getMnemonic()==Mnemonic_MUL); + assert((inst->getMnemonic() == Mnemonic_IMUL) || (inst->getMnemonic() == Mnemonic_MUL)); + if (inst->getForm() == Inst::Form_Native) { return Changed_Nothing; } + Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); - Opnd* dst = inst->getOpnd(defs.begin()); - if (defs.next(defs.begin())!=defs.end()) { + Opnd* dst1 = inst->getOpnd(defs.begin()); + Opnd* dst2 = NULL; + if ((inst->getMnemonic() == Mnemonic_IMUL) && (defs.next(defs.begin()) != defs.end())){ return Changed_Nothing; } + else { //inst->getMnemonic() == Mnemonic_MUL + dst2 = inst->getOpnd(defs.next(defs.begin())); + if (defs.next(defs.next(defs.begin()))!=defs.end()) + return Changed_Nothing; + } + Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* src1= inst->getOpnd(uses.begin()); Opnd* src2= inst->getOpnd(uses.next(uses.begin())); - assert(src1!=NULL && src2!=NULL && dst!=NULL); + if (inst->getMnemonic() == Mnemonic_IMUL) + assert(src1!=NULL && src2!=NULL && dst1!=NULL); + else //inst->getMnemonic() == Mnemonic_MUL + assert(src1!=NULL && src2!=NULL && dst1!=NULL && dst2!=NULL); + if (isImm(src1)) { Opnd* tmp = src1; src1 = src2; src2 = tmp; } @@ -648,33 +662,49 @@ int immVal = (int)src2->getImmValue(); if (immVal == 0) { if (Log::isEnabled()) Log::out()<<"I"<getId()<<" -> MUL with 0"<newCopyPseudoInst(Mnemonic_MOV, dst, src2)->insertAfter(inst); + if (inst->getMnemonic() == Mnemonic_IMUL) + irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src2)->insertAfter(inst); + else { //inst->getMnemonic() == Mnemonic_MUL + irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src2)->insertAfter(inst); + irManager->newCopyPseudoInst(Mnemonic_MOV, dst2, src2)->insertAfter(inst); + } inst->unlink(); return Changed_Inst; } else if (immVal == 1) { if (Log::isEnabled()) Log::out()<<"I"<getId()<<" -> MUL with 1"<newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst); + if (inst->getMnemonic() == Mnemonic_IMUL) + irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src1)->insertAfter(inst); + else { //inst->getMnemonic() == Mnemonic_MUL + irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, + irManager->newImmOpnd(dst1->getType(), 0))->insertAfter(inst); + irManager->newCopyPseudoInst(Mnemonic_MOV, dst2, src1)->insertAfter(inst); + } inst->unlink(); return Changed_Inst; } else if (immVal == 2) { - if (Log::isEnabled()) Log::out()<<"I"<getId()<<" -> MUL with 2"<newInstEx(Mnemonic_ADD, 1, dst, src1, src1)->insertAfter(inst); - inst->unlink(); - return Changed_Inst; - } else { - int minBit=getMinBit(immVal); - int maxBit=getMaxBit(immVal); - if (minBit == maxBit) { - assert(minBit>=2); - if (Log::isEnabled()) Log::out()<<"I"<getId()<<" -> MUL with 2^"<getTypeManager().getUInt32Type(); - irManager->newInstEx(Mnemonic_SHL, 1, dst, src1, irManager->newImmOpnd(int32Type, minBit))->insertAfter(inst); + if (inst->getMnemonic() == Mnemonic_IMUL) { + if (Log::isEnabled()) Log::out()<<"I"<getId()<<" -> MUL with 2"<newInstEx(Mnemonic_ADD, 1, dst1, src1, src1)->insertAfter(inst); inst->unlink(); return Changed_Inst; } - } - } - return Changed_Nothing; + } else { + if (inst->getMnemonic() == Mnemonic_IMUL) { + int minBit=getMinBit(immVal); + int maxBit=getMaxBit(immVal); + if (minBit == maxBit) { + assert(minBit>=2); + if (Log::isEnabled()) Log::out()<<"I"<getId()<<" -> MUL with 2^"<getTypeManager().getUInt8Type(); + irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src1)->insertBefore(inst); + irManager->newInst(Mnemonic_SHL, dst1, irManager->newImmOpnd(immType, minBit))->insertBefore(inst); + inst->unlink(); + return Changed_Inst; + } + } + } + } + return Changed_Nothing; } PeepHoleOpt::Changed PeepHoleOpt::handleInst_ALU(Inst* inst) @@ -730,6 +760,61 @@ return Changed_Inst; } } + } else if (mnemonic == Mnemonic_ADD) { + Inst *next = inst->getNextInst(); + if ((next) && (next->getMnemonic() == Mnemonic_ADC)) + return Changed_Nothing; + Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); + Opnd* dst = inst->getOpnd(defs.begin()); + Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); + Opnd* src1= inst->getOpnd(uses.begin()); + Opnd* src2= inst->getOpnd(uses.next(uses.begin())); + + if (isImm(src1) && isImm(src2)) { + int64 immSrc1 = src1->getImmValue(); + int64 immSrc2 = src2->getImmValue(); + if ((immSrc1 == 0) && (immSrc1 == 0)) { + irManager->newCopyPseudoInst(Mnemonic_MOV, dst, + irManager->newImmOpnd(dst->getType(), 0))->insertAfter(inst); + inst->unlink(); + return Changed_Inst; + } + } else if (isImm(src1) || isImm(src2)) { + if (isImm(src1)) { + Opnd* tmp = src1; src1 = src2; src2 = tmp; + } + if (src2->getImmValue() == 0) { + irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst); + inst->unlink(); + return Changed_Inst; + } + } + } else if (mnemonic == Mnemonic_SUB) { + Inst *next = inst->getNextInst(); + if ((next) && (next->getMnemonic() == Mnemonic_SBB)) + return Changed_Nothing; + Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); + Opnd* dst = inst->getOpnd(defs.begin()); + Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); + Opnd* src1= inst->getOpnd(uses.begin()); + Opnd* src2= inst->getOpnd(uses.next(uses.begin())); + + if (isImm(src1) && isImm(src2)) { + int64 immSrc1 = src1->getImmValue(); + int64 immSrc2 = src2->getImmValue(); + if ((immSrc1 == 0) && (immSrc1 == 0)) { + irManager->newCopyPseudoInst(Mnemonic_MOV, dst, + irManager->newImmOpnd(dst->getType(), 0))->insertAfter(inst); + inst->unlink(); + return Changed_Inst; + } + } else if (isImm(src2)) { + if (src2->getImmValue() == 0) { + irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst); + inst->unlink(); + return Changed_Inst; + } + } } return Changed_Nothing; } Index: working_vm/vm/jitrino/src/codegenerator/ia32/Ia32EarlyPropagation.cpp =================================================================== --- working_vm/vm/jitrino/src/codegenerator/ia32/Ia32EarlyPropagation.cpp £¨ÐÞ¶©°æ 707991£© +++ working_vm/vm/jitrino/src/codegenerator/ia32/Ia32EarlyPropagation.cpp £¨¹¤×÷¿½±´£© @@ -66,149 +66,247 @@ bool toIsGCType = toType->isObject() || toType->isManagedPtr(); return fromIsGCType == toIsGCType; } - //___________________________________________________________________________________________________ void EarlyPropagation::runImpl() -{ - irManager->updateLoopInfo(); - U_32 opndCount=irManager->getOpndCount(); +{ + irManager->updateLoopInfo(); + U_32 opndCount=irManager->getOpndCount(); - MemoryManager mm("early_prop"); - OpndInfo * opndInfos = new(mm) OpndInfo[opndCount]; - Node * currentLoopHeader = NULL; + MemoryManager mm("early_prop"); + OpndInfo * opndInfos = new(mm) OpndInfo[opndCount]; + Node * currentLoopHeader = NULL; - bool anyInstHandled=false; + 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++; - } + 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]; + 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; + 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<hasKind(Inst::Kind_PseudoInst) || irManager->isGCSafePoint(inst) || - opndInfo.sourceInst != inst->getPrevInst() || assignedOpndPropagated || + 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<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; - } + opndInfo.sourceOpndId = EmptyUint32; + assignedOpndPropagated = true; } } } - if (opndInfo.defCount > 1){ - opndInfo.sourceOpndId = EmptyUint32; + } + if ((opndInfo.defCount > 1) && (opndInfo.sourceOpndId != EmptyUint32)) { + 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; } } - /* - 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. + if (instHandled){ + if (opndInfos[opndInfo->sourceOpndId].sourceOpndId != EmptyUint32) + opndInfo->sourceOpndId = opndInfos[opndInfo->sourceOpndId].sourceOpndId; + opndInfo->sourceOpndDefCountAtCopy = opndInfos[opndInfo->sourceOpndId].defCount; + anyInstHandled=true; + } + } + } + } - 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 (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 (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 (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); + } } } + } - 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(); + /* Local constant/copy propagation */ + for (Nodes::const_reverse_iterator it = postOrdered.rbegin(), end = postOrdered.rend(); it!=end; ++it) { + Node * node=*it; + if (!node->isBlockNode()) { + continue; + } + + // Opnd ==> Latest Def by MOV (MOV dst{reg}, src{reg} or MOV dst{reg}, src{imm}) + // move transparent - + // MOV dst1{reg}, src1{reg} (map: dst1 => src1) + // MOV dst2{reg}, dst1{reg} (map: dst2 => src1) + StlHashMap localLastestDefMap(irManager->getMemoryManager()); + + // Traverse all INST in a BB in preorder + // For all INST - + // STEP 1: substitute a use with its non-null Latest Def by MOV + // STEP 2: clear non-null Latest Def by MOV of a def + // STEP 3: clear every non-null Latest Def by MOV which is a def + // For move INST which could update the map - + // STEP 1: try to update Latest Def by MOV of dst with the non-null Lastest Def by MOV of src + // STEP 2: if Lastest Def by MOV of src is null, update Latest Def by MOV of dst with src + for (Inst * inst = (Inst*)node->getFirstInst(); inst != NULL; inst=inst->getNextInst()) { + const bool isCopy = inst->getMnemonic() == Mnemonic_MOV; + + 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) { + // do propagation + if ((roles & Inst::OpndRole_All & Inst::OpndRole_FromEncoder) + && (roles & Inst::OpndRole_All & Inst::OpndRole_ForIterator) + && (roles & Inst::OpndRole_Changeable) && ((roles & Inst::OpndRole_Def) == 0) + && localLastestDefMap[opnd]) { + if (opnd->getType()->isUnmanagedPtr() && localLastestDefMap[opnd]->getType()->isInteger()) + localLastestDefMap[opnd]->setType(opnd->getType()); + inst->setOpnd(it, localLastestDefMap[opnd]); } - 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; + } + } + + 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) { + // update map + if (localLastestDefMap[opnd]) { + localLastestDefMap[opnd] = NULL; } + StlHashMap::iterator iter; + for(iter = localLastestDefMap.begin(); iter!=localLastestDefMap.end(); ++iter) { + if (iter->second == opnd) { + localLastestDefMap[iter->first] = NULL; + } + } } } - 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; + if (isCopy) { + 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; } - for (Inst * inst = (Inst*)node->getFirstInst(); inst != NULL; inst=inst->getNextInst()){ - inst->replaceOpnds(replacements); - } } + + 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)) { + // update map + if (localLastestDefMap[src]) + localLastestDefMap[dst] = localLastestDefMap[src]; + else + localLastestDefMap[dst] = src; + } + } } } + } + }