Index: vm/jitrino/src/codegenerator/ia32/Ia32CgUtils.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32CgUtils.cpp (revision 644680) +++ vm/jitrino/src/codegenerator/ia32/Ia32CgUtils.cpp (working copy) @@ -94,7 +94,22 @@ return isImm(opnd) || (opnd->getDefiningInst() != NULL); } +bool OpndUtils::isNoDefBetweenInsts(const Opnd* opnd, Inst* first, Inst* last) +{ + if (first->getNode() != last->getNode()) + return false; + for (Inst* i = first->getNextInst(); i != last; i = i->getNextInst()) + { + uint32 defcount = i->getOpndCount(Inst::OpndRole_Explicit|Inst::OpndRole_Def); + for (uint32 j=0; jgetOpnd(j)->getId() == opnd->getId()) + return false; + } + + return true; +} + const void* OpndUtils::extractAddrOfConst(const Opnd* op) { if (op->getMemOpndKind() != MemOpndKind_ConstantArea) { Index: vm/jitrino/src/codegenerator/ia32/Ia32CgUtils.h =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32CgUtils.h (revision 644680) +++ vm/jitrino/src/codegenerator/ia32/Ia32CgUtils.h (working copy) @@ -62,6 +62,12 @@ * Tests whether the Opnd has only one def. */ static bool isSingleDef(const Opnd* opnd); + + /** + * Tests whether the Opnd has no defs between two insts (excluding them). + * Checks only one basic block + */ + static bool isNoDefBetweenInsts(const Opnd* opnd, Inst* first, Inst* last); /** * Tests whether the given operand is placed on (any) register and Index: vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (revision 644680) +++ vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (working copy) @@ -46,6 +46,7 @@ typedef StlMap OPND_PAIRS_MAP; typedef StlVector INST_ARRAY; typedef StlMap INST_TO_NODE_MAP; + typedef StlMap OPND_TO_INST_MAP; // // virtuals // @@ -178,6 +179,13 @@ * The pointer points to the local variable in runImpl(); */ INST_TO_NODE_MAP* m_pLoopInfos; + /** + * Points to a set of 64bit operands that have null high part + * after using some instructions (for example, AND FFFFFFFFh), mapped to such instructions + * + * The pointer points to the local variable in runImpl(); + */ + OPND_TO_INST_MAP* m_pNullHPOpnds; }; static const char* help = @@ -235,6 +243,9 @@ INST_TO_NODE_MAP loopInfos(memMgr); m_pLoopInfos = &loopInfos; + OPND_TO_INST_MAP nullHPOpnds(memMgr); + m_pNullHPOpnds = &nullHPOpnds; + irManager->calculateOpndStatistics(); const Nodes* postOrder = &fg->getNodesPostOrder(); @@ -295,21 +306,29 @@ } cdq = inst; } else if ( cdq && inst->getMnemonic() == Mnemonic_AND && - isZeroImm(inst->getOpnd(defCount+1)) && - cdq->getOpnd(0)==inst->getOpnd(defCount)) { + ( isZeroImm(inst->getOpnd(defCount+1)) && cdq->getOpnd(0)==inst->getOpnd(defCount) || + isZeroImm(inst->getOpnd(defCount)) && cdq->getOpnd(0)==inst->getOpnd(defCount+1) ) ) { Inst * tmpInst = irManager->newCopyPseudoInst(Mnemonic_MOV,inst->getOpnd(0), irManager->newImmOpnd(inst->getOpnd(0)->getType(),0)); tmpInst->insertAfter(inst); inst->unlink(); inst = tmpInst; cdq->unlink(); cdq = NULL; - } else if ( inst->getMnemonic() == Mnemonic_AND && - isImm(inst->getOpnd(defCount+1)) && - inst->getOpnd(defCount+1)->getImmValue() == 0xFFFFFFFF) { - Inst * tmpInst = irManager->newCopyPseudoInst(Mnemonic_MOV,inst->getOpnd(0), inst->getOpnd(defCount)); - tmpInst->insertAfter(inst); - inst->unlink(); - inst = tmpInst; + } else if ( inst->getMnemonic() == Mnemonic_AND ) + { + if ( isImm(inst->getOpnd(defCount+1)) && inst->getOpnd(defCount+1)->getImmValue() == 0xFFFFFFFF ) + { + Inst * tmpInst = irManager->newCopyPseudoInst(Mnemonic_MOV,inst->getOpnd(0), inst->getOpnd(defCount)); + tmpInst->insertAfter(inst); + inst->unlink(); + inst = tmpInst; + } + else if ( isImm(inst->getOpnd(defCount)) && inst->getOpnd(defCount)->getImmValue() == 0xFFFFFFFF ) { + Inst * tmpInst = irManager->newCopyPseudoInst(Mnemonic_MOV,inst->getOpnd(0), inst->getOpnd(defCount+1)); + tmpInst->insertAfter(inst); + inst->unlink(); + inst = tmpInst; + } } } } @@ -494,6 +513,18 @@ irManager->newInstEx(Mnemonic_SBB, 1, dst_2, src1_2, src2_2)->insertBefore(inst); break; case Mnemonic_AND : + { + irManager->newInstEx(mn, 1, dst_1, src1_1, src2_1)->insertBefore(inst); + Inst* nullHighPart = irManager->newInstEx(mn, 1, dst_2, src1_2, src2_2); + nullHighPart->insertBefore(inst); + if (isImm(src1_2) && src1_2->getImmValue() == 0 || + isImm(src2_2) && src2_2->getImmValue() == 0) + { + (*m_pNullHPOpnds)[dst_2] = nullHighPart; + } + + break; + } case Mnemonic_OR : case Mnemonic_XOR : assert(dst_1 && src1_1 && src2_1); @@ -508,7 +539,12 @@ assert(dst_1 && src1_1); irManager->newCopyPseudoInst(Mnemonic_MOV, dst_1, src1_1)->insertBefore(inst); if (dst_2 && src1_2) { - irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, src1_2)->insertBefore(inst); + Inst* nullHighPart = irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, src1_2); + nullHighPart->insertBefore(inst); + if (isImm(src1_2) && src1_2->getImmValue() == 0) + { + (*m_pNullHPOpnds)[dst_2] = nullHighPart; + } } break; case Mnemonic_MOVSX : @@ -532,11 +568,14 @@ //setns hi ; if lo is positive, then load 1 into hi //sub hi, 1 ; if lo is positive, then hi is now '0'. otherwise, it's -1 irManager->newInstEx(Mnemonic_CDQ, 1, dst_2, dst_1)->insertBefore(inst); - } else { + } else { //fill upper word with 0 assert(mn == Mnemonic_MOVZX); Opnd* imm0=irManager->newImmOpnd(irManager->getTypeManager().getInt32Type(), 0); - irManager->newInstEx(Mnemonic_MOV, 1, dst_2, imm0)->insertBefore(inst); + Inst* nullHighPart = irManager->newInstEx(Mnemonic_MOV, 1, dst_2, imm0); + nullHighPart->insertBefore(inst); + //dst_2 = imm0; + (*m_pNullHPOpnds)[dst_2] = nullHighPart; } break; case Mnemonic_PUSH : @@ -610,13 +649,17 @@ if (immVal == 32) { irManager->newCopyPseudoInst(Mnemonic_MOV, dst_1, src1_2)->insertBefore(inst); if (mnem != Mnemonic_SAR) { - irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, irManager->newImmOpnd(src1_1->getType(), 0))->insertBefore(inst); + Inst* nullHighPart = irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, irManager->newImmOpnd(src1_1->getType(), 0)); + nullHighPart->insertBefore(inst); + (*m_pNullHPOpnds)[dst_2] = nullHighPart; } else { irManager->newInstEx(mnem, 1, dst_2, src1_2, irManager->newImmOpnd(src2->getType(), 31))->insertBefore(inst); } } else if(immVal > 31) { if (mnem != Mnemonic_SAR) { - irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, irManager->newImmOpnd(src1_1->getType(), 0))->insertBefore(inst); + Inst* nullHighPart = irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, irManager->newImmOpnd(src1_1->getType(), 0)); + nullHighPart->insertBefore(inst); + (*m_pNullHPOpnds)[dst_2] = nullHighPart; } else { irManager->newInstEx(mnem, 1, dst_2, src1_2, irManager->newImmOpnd(src2->getType(), 31))->insertBefore(inst); } @@ -925,6 +968,18 @@ prepareNewOpnds(src1, src1_1, src1_2); prepareNewOpnds(src2, src2_1, src2_2); + bool src1NullHighPart = false; + bool src2NullHighPart = false; + + if(m_pNullHPOpnds->find(src1_2)!=m_pNullHPOpnds->end()) { + Inst* nullInst = (*m_pNullHPOpnds)[src1_2]; + src1NullHighPart = isNoDefBetweenInsts(src1_2, nullInst, inst); + } + if(m_pNullHPOpnds->find(src2_2)!=m_pNullHPOpnds->end()) { + Inst* nullInst = (*m_pNullHPOpnds)[src2_2]; + src2NullHighPart = isNoDefBetweenInsts(src2_2, nullInst, inst); + } + TypeManager& tm = irManager->getTypeManager(); Type* int32type = tm.getInt32Type(); // Name them eax, ecx, edx here, in code only, to refer same regs as in @@ -1012,20 +1067,30 @@ entryNode = (Node*)0xDEADBEEF; setCurrentNode(longMulNode); - /* mov eax, a_lo*/ newInst(Mnemonic_MOV, eax, a_lo); - /* mul b_hi */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_hi); - // - // Now, EAX=a_lo*b_hi, EDX content is dropped - // - // save a_lo*b_hi(EAX) - /* mov ecx, eax */ newInst(Mnemonic_MOV, ecx, eax); - /* mov eax, a_hi*/ newInst(Mnemonic_MOV, eax, a_hi); - /* mul b_lo */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo); - /* add ecx, eax */ newInst(Mnemonic_ADD, 1, ecx, ecx, eax); - + if (!src2NullHighPart) + { + /* mov eax, a_lo*/ newInst(Mnemonic_MOV, eax, a_lo); + /* mul b_hi */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_hi); + // + // Now, EAX=a_lo*b_hi, EDX content is dropped + // + // save a_lo*b_hi(EAX) + /* mov ecx, eax */ newInst(Mnemonic_MOV, ecx, eax); + } + if (!src1NullHighPart) + { + /* mov eax, a_hi*/ newInst(Mnemonic_MOV, eax, a_hi); + /* mul b_lo */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo); + if (!src2NullHighPart) + /* add ecx, eax */ newInst(Mnemonic_ADD, 1, ecx, ecx, eax); + else + newInst(Mnemonic_MOV, ecx, eax); + } /* mov eax, a_lo */ newInst(Mnemonic_MOV, eax, a_lo); /* mul b_lo */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo); - /* add edx, ecx */ newInst(Mnemonic_ADD, 1, edx, edx, ecx); + if (!src1NullHighPart || !src2NullHighPart) + /* add edx, ecx */ newInst(Mnemonic_ADD, 1, edx, edx, ecx); + connectNodes(longMulNode, storeResultNode); setCurrentNode(NULL); longMulNode = (Node*)0xDEADBEEF; @@ -1521,3 +1586,6 @@ }} + + +