bool Opnd::isImm(int size) { if (isImm() == false) return false; Opnd* imm = (Opnd*) this; if (Opnd::isFoldableImm(imm->getValue(), size)) return true; return false; }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_CMP(Inst* inst) { assert(inst->getMnemonic()==Mnemonic_CMP); 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); if (isImm(src1)) { Opnd* tmp = src1; src1 = src2; src2 = tmp; } if (isImm(src2) && isReg(src1) && (int)src2->getImmValue() == 0) { if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> CMP with 0"<<std::endl; irManager->newInst(Mnemonic_TEST, src1, src1)->insertAfter(inst); inst->unlink(); return Changed_Inst; } return Changed_Nothing; }
bool OpndUtils::isSingleDef(const Opnd* opnd) { return isImm(opnd) || (opnd->getDefiningInst() != NULL); }
bool OpndUtils::isZeroImm(const Opnd* op) { return isImm(op, 0); }
bool OpndUtils::fitsImm8(const Opnd* op) { return isImm(op) && (CHAR_MIN <= op->getImmValue() && op->getImmValue() <= CHAR_MAX); }
bool OpndUtils::isImm32(const Opnd* op) { return isImm(op) && op->getSize() == OpndSize_32; }
bool OpndUtils::isImm(const Opnd* op, int iVal) { return isImm(op) && (op->getImmValue() == iVal); }
const char *Operand::string() const { static char string[256]; if(isVoid(type)) { return 0; } else if(isImm(type)) { if(reference) { return reference; } else { if(value <= 127 && value >= -128) { snprintf(string, 255, "0x%0.2X", value & 0xFF); } else if(value <= 32767 && value -32768) { snprintf(string, 255, "0x%0.4X", value & 0xFFFF); } else { snprintf(string, 255, "0x%0.8X", value); } } } else if(isReg(type)) { return regName(); } else if(isMem(type)) { switch(type) { case OPERAND_MEM8: snprintf(string, 255, "byte ptr ["); break; case OPERAND_MEM16: snprintf(string, 255, "word ptr ["); break; case OPERAND_MEM32: snprintf(string, 255, "dword ptr ["); break; case OPERAND_MEM64: snprintf(string, 255, "qword ptr ["); break; case OPERAND_MEM128: snprintf(string, 255, "xmmword ptr ["); break; case OPERAND_MEM: default: snprintf(string, 255, "byte ptr ["); } if(baseReg != Encoding::REG_UNKNOWN) { snprintf(string, 255, "%s%s", string, regName()); if(indexReg != Encoding::REG_UNKNOWN) { snprintf(string, 255, "%s+", string); } } if(indexReg != Encoding::REG_UNKNOWN) { snprintf(string, 255, "%s%s", string, indexName()); } switch(scale) { case 0: case 1: break; case 2: snprintf(string, 255, "%s*2", string); break; case 4: snprintf(string, 255, "%s*4", string); break; case 8: snprintf(string, 255, "%s*8", string); break; default: throw INTERNAL_ERROR; } if(displacement) { if(baseReg != Encoding::REG_UNKNOWN || indexReg != Encoding::REG_UNKNOWN) { snprintf(string, 255, "%s+", string); } if(reference) { snprintf(string, 255, "%s%s", string, reference); } else { if(displacement <= 32767 && displacement >= -32768) { snprintf(string, 255, "%s%d", string, displacement); } else { snprintf(string, 255, "%s0x%0.8X", string, displacement); } } } snprintf(string, 255, "%s]", string); } else { throw INTERNAL_ERROR; } return strlwr(string); }
bool Operand::isImm(const Operand &operand) { return isImm(operand.type); }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SETcc(Inst* inst) { if (((BasicBlock*)inst->getNode())->getLayoutSucc() == NULL) { Mnemonic mn = inst->getMnemonic(); Inst* prev = inst->getPrevInst(); Inst *next = inst->getNextInst(); Node *currNode = inst->getNode(); bool methodMarkerOccur = false; MethodMarkerPseudoInst* methodMarker = NULL; // ignoring instructions that have no effect and saving method markers to correct them during optimizations while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP) { if (next == NULL) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getKind() == Node::Kind_Exit) return Changed_Nothing; next = (Inst*) currNode->getFirstInst(); } else { if (next->getKind() == Inst::Kind_MethodEndPseudoInst) { //max 1 saved method marker if (methodMarkerOccur) { return Changed_Nothing; } methodMarker = (MethodMarkerPseudoInst*)next; methodMarkerOccur = true; } next = next->getNextInst(); } } Inst *next2 = next->getNextInst(); bool step1 = true; currNode = inst->getNode(); while (currNode != next->getNode()) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getInDegree()!=1) { step1 = false; break; } } // step1: // ------------------------------------------ // MOV opnd, 0 MOV opnd2, 0 // SETcc opnd -> SETcc opnd2 // MOV opnd2, opnd // ------------------------------------------ // nb: applicable if opnd will not be used further if (step1 && prev!= NULL && prev->getMnemonic() == Mnemonic_MOV && next!= NULL && next->getMnemonic() == Mnemonic_MOV) { Opnd *prevopnd1, *prevopnd2, *nextopnd1, *nextopnd2, *setopnd; if (prev->getKind() == Inst::Kind_CopyPseudoInst) { prevopnd1 = prev->getOpnd(0); prevopnd2 = prev->getOpnd(1); } else { Inst::Opnds prevuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds prevdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def); prevopnd1 = prev->getOpnd(prevdefs.begin()); prevopnd2 = prev->getOpnd(prevuses.begin()); } if (next->getKind() == Inst::Kind_CopyPseudoInst) { nextopnd1 = next->getOpnd(0); nextopnd2 = next->getOpnd(1); } else { Inst::Opnds nextuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds nextdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def); nextopnd1 = next->getOpnd(nextdefs.begin()); nextopnd2 = next->getOpnd(nextuses.begin()); } Inst::Opnds setdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); setopnd = inst->getOpnd(setdefs.begin()); if (isReg(nextopnd1) && prevopnd1->getId() == setopnd->getId() && setopnd->getId() == nextopnd2->getId() && isImm(prevopnd2) && prevopnd2->getImmValue() == 0 ) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(next->getNode(), ls); for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) { irManager->updateLiveness(i, ls); } bool opndNotUsed = !ls.getBit(setopnd->getId()); if (opndNotUsed) { if (nextopnd1->getRegName() != RegName_Null && Constraint::getAliasRegName(nextopnd1->getRegName(), OpndSize_8) == RegName_Null) { nextopnd1->assignRegName(setopnd->getRegName()); } irManager->newInst(Mnemonic_MOV, nextopnd1, prevopnd2)->insertBefore(inst); irManager->newInst(mn, nextopnd1)->insertBefore(inst); prev->unlink(); inst->unlink(); next->unlink(); return Changed_Node; } } } // step2: // -------------------------------------------------------------- // MOV opnd, 0 Jcc smwh Jcc smwh // SETcc opnd -> BB1: v BB1: // CMP opnd, 0 ... // Jcc smwh CMP opnd, 0 // BB1: Jcc smwh // -------------------------------------------------------------- // nb: applicable if opnd will not be used further // nb: conditions of new jumps are calculated from conditions of old jump and set instructions if (prev!= NULL && prev->getMnemonic() == Mnemonic_MOV && next!= NULL && (next->getMnemonic() == Mnemonic_CMP || next->getMnemonic() == Mnemonic_TEST) && next2!= NULL && (next2->getMnemonic() == Mnemonic_JG || next2->getMnemonic() == Mnemonic_JE || next2->getMnemonic() == Mnemonic_JNE) ) { Opnd* movopnd1; Opnd* movopnd2; if (prev->getKind() == Inst::Kind_CopyPseudoInst) { movopnd1 = prev->getOpnd(0); movopnd2 = prev->getOpnd(1); } else { Inst::Opnds movuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds movdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def); movopnd1 = prev->getOpnd(movdefs.begin()); movopnd2 = prev->getOpnd(movuses.begin()); } Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin()); Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin())); if ( isImm(movopnd2) && movopnd2->getImmValue() == 0 && movopnd1->getId() == cmpopnd1->getId() && //case CMP: (next->getMnemonic() != Mnemonic_CMP || (isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)) && //case TEST: (next->getMnemonic() != Mnemonic_TEST || cmpopnd1->getId() == cmpopnd2->getId()) ) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(next2->getNode(), ls); bool opndNotUsed = !ls.getBit(movopnd1->getId()); if (opndNotUsed) { BranchInst* br = (BranchInst*) next2; Mnemonic newjumpmn = Mnemonic_JZ; if (next2->getMnemonic() == Mnemonic_JE) { switch (mn) { case Mnemonic_SETG: newjumpmn = Mnemonic_JLE; break; case Mnemonic_SETE: newjumpmn = Mnemonic_JNE; break; case Mnemonic_SETL: newjumpmn = Mnemonic_JGE; break; case Mnemonic_SETNE: newjumpmn = Mnemonic_JE; break; default: assert(0); break; } } else { switch (mn) { case Mnemonic_SETG: newjumpmn = Mnemonic_JG; break; case Mnemonic_SETE: newjumpmn = Mnemonic_JE; break; case Mnemonic_SETL: newjumpmn = Mnemonic_JL; break; case Mnemonic_SETNE: newjumpmn = Mnemonic_JNE; break; default: assert(0); break; } } if (inst->getNode()->getId() != next->getNode()->getId()) { ControlFlowGraph* cfg = irManager->getFlowGraph(); cfg->removeEdge(inst->getNode()->getOutEdge(Edge::Kind_Unconditional)); double trueEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_True)->getEdgeProb(); double falseEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_False)->getEdgeProb(); cfg->addEdge(inst->getNode(), br->getTrueTarget(), trueEdgeProb); cfg->addEdge(inst->getNode(), br->getFalseTarget(), falseEdgeProb); irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(inst); if (methodMarkerOccur) { inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc())); } prev->unlink(); inst->unlink(); cfg->purgeUnreachableNodes(); } else { irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(next2); prev->unlink(); inst->unlink(); next->unlink(); next2->unlink(); } return Changed_Node; }// endif opndNotUsed } } } return Changed_Nothing; }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_ALU(Inst* inst) { // The normal form is 'OPERATION left opnd, right operand' // except for NOT operation. const Mnemonic mnemonic = inst->getMnemonic(); if (mnemonic == Mnemonic_NOT) { // No optimizations this time return Changed_Nothing; } // Only these mnemonics have the majestic name of ALUs. assert(mnemonic == Mnemonic_ADD || mnemonic == Mnemonic_SUB || mnemonic == Mnemonic_ADC || mnemonic == Mnemonic_SBB || mnemonic == Mnemonic_OR || mnemonic == Mnemonic_XOR || mnemonic == Mnemonic_AND || mnemonic == Mnemonic_CMP || mnemonic == Mnemonic_TEST); if (mnemonic == Mnemonic_AND) { 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())); Opnd *newopnd2; // test can work only with operands having equal sizes if (isImm(src2) && src2->getSize() != src1->getSize()) newopnd2 = irManager->newImmOpnd(src1->getType(), src2->getImmValue()); else newopnd2 = src2; if (!isMem(dst) && !isMem(src1) && !isMem(src2)) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(inst->getNode(), ls); for (Inst* i = (Inst*)inst->getNode()->getLastInst(); i!=inst; i = i->getPrevInst()) { irManager->updateLiveness(i, ls); } bool dstNotUsed = !ls.getBit(dst->getId()); if (dstNotUsed) { // what: AND opnd1, opnd2 => TEST opnd1, opnd2 // nb: applicable if opnd1 will not be used further if (inst->getForm() == Inst::Form_Extended) irManager->newInstEx(Mnemonic_TEST, 0, src1, newopnd2)->insertAfter(inst); else irManager->newInst(Mnemonic_TEST, src1, newopnd2)->insertAfter(inst); inst->unlink(); return Changed_Inst; } } } else if (mnemonic == Mnemonic_ADD) { /* Change "dst=src+0" to "MOV dst, src" if there is another ADD inst followed in the same BB. */ 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())); bool src1IsZero = false; bool src2IsZero = false; if (src1->isPlacedIn(OpndKind_Imm) && (src1->getImmValue() == 0)) src1IsZero = true; if (src2->isPlacedIn(OpndKind_Imm) && (src2->getImmValue() == 0)) src2IsZero = true; bool anotherADD = false; Inst *iter = inst->getNextInst(); while (iter != NULL) { if (iter->getMnemonic() == Mnemonic_ADC) break; if (iter->getMnemonic() == Mnemonic_ADD) { anotherADD = true; break; } iter = iter->getNextInst();; } if (anotherADD) { if (src1IsZero) { irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src2)->insertAfter(inst); inst->unlink(); return Changed_Inst; } else if (src2IsZero) { irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst); inst->unlink(); return Changed_Inst; } } } return Changed_Nothing; }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_MUL(Inst* inst) { 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* 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())); 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; } if (isImm(src2) && irManager->getTypeSize(src2->getType()) <=32) { int immVal = (int)src2->getImmValue(); if (immVal == 0) { if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 0"<<std::endl; 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"<<inst->getId()<<" -> MUL with 1"<<std::endl; if (inst->getMnemonic() == Mnemonic_IMUL) { irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src1)->insertAfter(inst); } else { //inst->getMnemonic() == Mnemonic_MUL Opnd* zero = irManager->newImmOpnd(dst1->getType(), 0); irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, zero)->insertAfter(inst); irManager->newCopyPseudoInst(Mnemonic_MOV, dst2, src1)->insertAfter(inst); } inst->unlink(); return Changed_Inst; } else if (immVal == 2) { if (inst->getMnemonic() == Mnemonic_IMUL) { if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 2"<<std::endl; irManager->newInstEx(Mnemonic_ADD, 1, dst1, src1, src1)->insertAfter(inst); inst->unlink(); return Changed_Inst; } } 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"<<inst->getId()<<" -> MUL with 2^"<<minBit<<std::endl; Type* immType = irManager->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_MOV(Inst* inst) { Node* node = inst->getNode(); if (((BasicBlock*)node)->getLayoutSucc() == NULL) { Inst *next = inst->getNextInst(); Node *currNode = node; bool methodMarkerOccur = false; MethodMarkerPseudoInst* methodMarker = NULL; // ignoring instructions that have no effect and saving method markers to correct them during optimizations while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP) { if (next == NULL) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getKind() == Node::Kind_Exit) return Changed_Nothing; next = (Inst*) currNode->getFirstInst(); } else { if (next->getKind() == Inst::Kind_MethodEndPseudoInst) { //max 1 saved method marker if (methodMarkerOccur) { return Changed_Nothing; } methodMarker = (MethodMarkerPseudoInst*)next; methodMarkerOccur = true; } next = next->getNextInst(); } } Inst *jump = next->getNextInst(); bool step1 = true; currNode = node; while (currNode != next->getNode()) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getInDegree()!=1) { step1 = false; break; } } // step1: // --------------------------------------------- // MOV opnd, opnd2 MOV opnd3, opnd2 // MOV opnd3, opnd -> // --------------------------------------------- // nb: applicable if opnd will not be used further if (step1 && next->getMnemonic() == Mnemonic_MOV) { Opnd *movopnd1, *movopnd2, *nextmovopnd1, *nextmovopnd2; bool isInstCopyPseudo = (inst->getKind() == Inst::Kind_CopyPseudoInst); if (isInstCopyPseudo) { movopnd1 = inst->getOpnd(0); movopnd2 = inst->getOpnd(1); } else { Inst::Opnds movuses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds movdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); movopnd1 = inst->getOpnd(movdefs.begin()); movopnd2 = inst->getOpnd(movuses.begin()); } bool isNextCopyPseudo = (next->getKind() == Inst::Kind_CopyPseudoInst); if (isNextCopyPseudo) { nextmovopnd1 = next->getOpnd(0); nextmovopnd2 = next->getOpnd(1); } else { Inst::Opnds nextmovuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds nextmovdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def); nextmovopnd1 = next->getOpnd(nextmovdefs.begin()); nextmovopnd2 = next->getOpnd(nextmovuses.begin()); } if (movopnd1->getId() == nextmovopnd2->getId() && !isMem(movopnd2) && !isMem(nextmovopnd1) && !isMem(movopnd1) ) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(next->getNode(), ls); for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) { irManager->updateLiveness(i, ls); } bool dstNotUsed = !ls.getBit(movopnd1->getId()); if (dstNotUsed) { if (isInstCopyPseudo && isNextCopyPseudo) irManager->newCopyPseudoInst(Mnemonic_MOV, nextmovopnd1, movopnd2)->insertAfter(inst); else irManager->newInst(Mnemonic_MOV, nextmovopnd1, movopnd2)->insertAfter(inst); inst->unlink(); next->unlink(); return Changed_Node; } } } // step2: // -------------------------------------------------------------- // MOV opnd, 0/1 Jmp smwh/BB1 Jmp smwh/BB1 // CMP opnd, 0 -> CMP opnd, 0 v // Jcc smwh Jcc smwh // BB1: BB1: // -------------------------------------------------------------- // nb: applicable if opnd will not be used further if (next->getMnemonic() == Mnemonic_CMP && jump!= NULL && (jump->getMnemonic() == Mnemonic_JE || jump->getMnemonic() == Mnemonic_JNE)) { Opnd *movopnd1, *movopnd2; if (inst->getKind() == Inst::Kind_CopyPseudoInst) { movopnd1 = inst->getOpnd(0); movopnd2 = inst->getOpnd(1); } else { Inst::Opnds movuses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds movdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); movopnd1 = inst->getOpnd(movdefs.begin()); movopnd2 = inst->getOpnd(movuses.begin()); } Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin()); Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin())); if (isImm(movopnd2) && (movopnd2->getImmValue() == 0 || movopnd2->getImmValue() == 1) && movopnd1->getId() == cmpopnd1->getId() && isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(jump->getNode(), ls); bool opndNotUsed = !ls.getBit(movopnd1->getId()); if (opndNotUsed) { ControlFlowGraph* cfg = irManager->getFlowGraph(); Node* destination = ((BranchInst*)jump)->getTrueTarget(); if ((jump->getMnemonic() == Mnemonic_JNE || movopnd2->getImmValue() == 1) && !(jump->getMnemonic() == Mnemonic_JNE && movopnd2->getImmValue() == 1)) { destination = ((BranchInst*)jump)->getFalseTarget(); } if (node->getId() != next->getNode()->getId()) { if (methodMarkerOccur) { inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc())); } inst->unlink(); Edge *outEdge = node->getOutEdge(Edge::Kind_Unconditional); cfg->replaceEdgeTarget(outEdge, destination, true); cfg->purgeUnreachableNodes(); // previous successor may become unreachable } else { cfg->removeEdge(node->getOutEdge(Edge::Kind_True)); cfg->removeEdge(node->getOutEdge(Edge::Kind_False)); cfg->addEdge(node, destination); inst->unlink(); next->unlink(); jump->unlink(); } return Changed_Node; } } } } return Changed_Nothing; }