PeepHoleOpt::Changed PeepHoleOpt::handleInst_SSEXor(Inst* inst) { assert(inst->getMnemonic() == Mnemonic_XORPS || inst->getMnemonic() == Mnemonic_XORPD); if (inst->getOpndCount() != 2) { // Expected only XORPS/PD a, b assert(false); return Changed_Nothing; } Opnd* dst = inst->getOpnd(0); Opnd* src = inst->getOpnd(1); if (isReg(dst) && isReg(src, dst->getRegName())) { /*what: XORPS/XORPD regN, regN => PXOR regN, regN why: XORPS/PD used for zero-ing register, but PXOR is faster (2 ticks on PXOR vs 4 ticks for XORPS/XORPD) */ // FIXME: replacing operands on 1 instruction only // will fail liveness verification if their refcount > 1 //dst = convertToXmmReg64(dst); //src = convertToXmmReg64(src); //Inst* ii = irManager->newInst(Mnemonic_PXOR, dst, src); //replaceInst(inst, ii); //return Changed_Inst; } return Changed_Nothing; }
bool Opnd::isMem() { if (isReg() == false) return false; if (value < S_BASE) return false; if (value >= LOCATION_INVALID) return false; return true; return true; }
bool Operand6502::isDPReg(char *str) { int reg; if (isReg(str, ®)) if (reg==16) return true; return false; }
int readReg(char * reg_name, int32_t* value) { //Lit dans un registre a travers value int i=isReg(reg_name); if(i==-1) { //test -1 et 0 non modifiable WARNING_MSG("%s isn't a valid register",reg_name); return -1; } else { *value=reg_mips[i]; return 0; } }
int writeReg(char * reg_name, int32_t value) { // Ecrit value dans un registre int i=isReg(reg_name); if(i<1) { //test -1 et 0 non modifiable WARNING_MSG("%s isn't a valid register",reg_name); return -1; } else { reg_mips[i]=value; return i; } }
bool OpndUtils::isXmmReg(const Opnd* op, RegName what) { if (!isReg(op)) { return false; } const RegName regName = op->getRegName(); if (getRegKind(regName) != OpndKind_XMMReg) { return false; } if (what == RegName_Null) { return true; } return regName == what; }
RVNGDirectoryStreamTest::RVNGDirectoryStreamTest() : m_dir(TEST_DIR) , m_file(TEST_DIR) , m_nonexistent(TEST_DIR) { m_file.append("/"); m_file.append(TEST_FILENAME); m_nonexistent.append("/"); m_nonexistent.append(TEST_NONEXISTENT); // dir m_nonexistent.append("/"); m_nonexistent.append(TEST_NONEXISTENT); // file // sanity check assert(isDir(m_dir.c_str())); assert(isReg(m_file.c_str())); assert(!exists(m_nonexistent.c_str())); }
void Tmp::dump(PrintStream& out) const { if (!*this) { out.print("<none>"); return; } if (isReg()) { out.print(reg()); return; } if (isGP()) { out.print("%tmp", gpTmpIndex()); return; } out.print("%ftmp", fpTmpIndex()); }
bool stm8notUsed (const char *what, lineNode *endPl, lineNode *head) { lineNode *pl; if(strcmp(what, "x") == 0) return(stm8notUsed("xl", endPl, head) && stm8notUsed("xh", endPl, head)); if(strcmp(what, "y") == 0) return(stm8notUsed("yl", endPl, head) && stm8notUsed("yh", endPl, head)); if(!isReg(what)) return FALSE; _G.head = head; unvisitLines (_G.head); pl = endPl->next; return (doTermScan (&pl, what)); }
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 Opnd::isWritable() { if (isReg() == false) return false; if (isConstant() == true) return false; return true; }
static bool printAlias(MCInst *MI, SStream *OS) { switch (MCInst_getOpcode(MI)) { case Mips_BEQ: // beq $zero, $zero, $L2 => b $L2 // beq $r0, $zero, $L2 => beqz $r0, $L2 return (isReg(MI, 0, Mips_ZERO) && isReg(MI, 1, Mips_ZERO) && printAlias1("b", MI, 2, OS)) || (isReg(MI, 1, Mips_ZERO) && printAlias2("beqz", MI, 0, 2, OS)); case Mips_BEQ64: // beq $r0, $zero, $L2 => beqz $r0, $L2 return isReg(MI, 1, Mips_ZERO_64) && printAlias2("beqz", MI, 0, 2, OS); case Mips_BNE: // bne $r0, $zero, $L2 => bnez $r0, $L2 return isReg(MI, 1, Mips_ZERO) && printAlias2("bnez", MI, 0, 2, OS); case Mips_BNE64: // bne $r0, $zero, $L2 => bnez $r0, $L2 return isReg(MI, 1, Mips_ZERO_64) && printAlias2("bnez", MI, 0, 2, OS); case Mips_BGEZAL: // bgezal $zero, $L1 => bal $L1 return isReg(MI, 0, Mips_ZERO) && printAlias1("bal", MI, 1, OS); case Mips_BC1T: // bc1t $fcc0, $L1 => bc1t $L1 return isReg(MI, 0, Mips_FCC0) && printAlias1("bc1t", MI, 1, OS); case Mips_BC1F: // bc1f $fcc0, $L1 => bc1f $L1 return isReg(MI, 0, Mips_FCC0) && printAlias1("bc1f", MI, 1, OS); case Mips_JALR: // jalr $ra, $r1 => jalr $r1 return isReg(MI, 0, Mips_RA) && printAlias1("jalr", MI, 1, OS); case Mips_JALR64: // jalr $ra, $r1 => jalr $r1 return isReg(MI, 0, Mips_RA_64) && printAlias1("jalr", MI, 1, OS); case Mips_NOR: case Mips_NOR_MM: // nor $r0, $r1, $zero => not $r0, $r1 return isReg(MI, 2, Mips_ZERO) && printAlias2("not", MI, 0, 1, OS); case Mips_NOR64: // nor $r0, $r1, $zero => not $r0, $r1 return isReg(MI, 2, Mips_ZERO_64) && printAlias2("not", MI, 0, 1, OS); case Mips_OR: // or $r0, $r1, $zero => move $r0, $r1 return isReg(MI, 2, Mips_ZERO) && printAlias2("move", MI, 0, 1, OS); default: return false; } }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SSEMov(Inst* inst) { assert(inst->getMnemonic() == Mnemonic_MOVSS || inst->getMnemonic() == Mnemonic_MOVSD); const bool isDouble = inst->getMnemonic() == Mnemonic_MOVSD; if (inst->getOpndCount() != 2) { // Expected only MOVSS/SD a, b assert(false); return Changed_Nothing; } Opnd* dst = inst->getOpnd(0); Opnd* src = inst->getOpnd(1); // // if (isReg(dst) && equals(src, dst)) { // what: same register moved around // why: useless thing inst->unlink(); return Changed_Inst; } // // if (isReg(dst) && isMem(src)) { /* what: MOVSS/MOVSD xmmreg, [zero constant from memory] => PXOR xmmreg, xmmreg why: shorter instruction; no memory access => faster nb: only works with 64 XMMs */ bool isZeroConstant = false; if (isDouble) { isZeroConstant = isFPConst(src, (double)0); } else { isZeroConstant = isFPConst(src, (float)0); } if (isZeroConstant) { // PXOR only accepts double registers, convert dst dst = convertToXmmReg64(dst); Inst* ii = irManager->newInst(Mnemonic_PXOR, dst, dst); replaceInst(inst, ii); return Changed_Inst; } // // fall through to process more // || // vv } // ~ movss xmm, 0 => pxor xmm,xmm if (isReg(dst) && isReg(src)) { /*what: MOVSS/MOVSD reg, reg => MOVQ reg, reg why: MOVSD has latency=6, MOVSS has latency=4, MOVQ's latency=2 nb: MOVQ only works with 64 xmms */ dst = convertToXmmReg64(dst); src = convertToXmmReg64(src); Inst* ii = irManager->newInst(Mnemonic_MOVQ, dst, src); replaceInst(inst, ii); return Changed_Inst; } // We just handled 'both regs' case above, the only possible variant: assert((isReg(dst)&&isMem(src)) || (isReg(src)&&isMem(dst))); if (false && isDouble) { //FIXME: MOVQ with memory gets encoded badly - need to fix in encoder /* what: MOVSD => MOVQ why: faster (? actually, I hope so. Need to double check) nb: only for xmm64 */ Inst* ii = irManager->newInst(Mnemonic_MOVQ, dst, src); replaceInst(inst, ii); return Changed_Inst; } return Changed_Nothing; }
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::isReg(const Operand &operand) { return isReg(operand.type); }
int stm8instructionSize(const lineNode *pl) { char *operand; char *op1start; char *op2start; int i = 0; operand = nextToken(pl->line); op1start = nextToken(NULL); op2start = nextToken(NULL); //fprintf(stderr, "op1start=%s op2start=%s\n", op1start, op2start); while(op2start && isspace(*op2start)) op2start++; //printf("operand=%s op1start=%s op2start=%s\n", operand, op1start, op2start); /* arity=1 */ if(EQUALS(operand, "clr") || EQUALS(operand, "dec") || EQUALS(operand, "inc") || EQUALS(operand, "push") || EQUALS(operand, "swap") || EQUALS(operand, "jp") || EQUALS(operand, "cpl") || EQUALS(operand, "tnz")) { if(!op1start) return(3); if(op1start[0] == 'a' || op1start[1] == 'x') return(1); if(op1start[1] == 'y') return(2); if(op1start[0] == '(') op1start++; if(strstr(op1start, ",y)")) i++; // costs extra byte for operating with y if(isLabel(op1start)) return(3); if(readint(op1start) <= 0xFF) return(2+i); /* op1 > 0xFF */ if(EQUALS(operand, "jp") && !strchr(op1start, 'y')) return(3); return(4); } if(EQUALS(operand, "exg")) { if(isReg(op2start)) return(1); else return(3); } if(EQUALS(operand, "addw") || EQUALS(operand, "subw")) { if(isImmediate(op2start) && op1start[0] == 'y') return(4); if(isImmediate(op2start)) return(3); if(isSpIndexed(op2start)) return(3); if(isLongoff(op2start, "x")) return(4); } if(EQUALS(operand, "cplw")) { if(op1start[0] == 'y') return(2); else return(1); } if(EQUALS(operand, "ldf")) { if(isRelativeAddr(op1start, "y") || isRelativeAddr(op2start, "y")) return(5); else return(4); } /* Operations that costs 2 or 3 bytes for immediate */ if(ISINST(operand, "ld") || EQUALS(operand, "cp") || EQUALS(operand, "cpw") || ISINST(operand, "adc") || EQUALS(operand, "add") || ISINST(operand, "and") || ISINST(operand, "bcp") || ISINST(operand, "call") || ISINST(operand, "callr") || ISINST(operand, "jr") || ISINST(operand, "or") || ISINST(operand, "sbc") || EQUALS(operand, "sub") || ISINST(operand, "xor")) { char suffix; if(!op1start || !op2start) return(4); suffix = operand[strlen(operand)-1]; if(suffix == 'w' && isImmediate(op2start)) i++; // costs extra byte if(isSpIndexed(op1start) || isSpIndexed(op2start)) return(2); if(!strcmp(op1start, "(x)") || !strcmp(op2start, "(x)")) return(1); if(!strcmp(op1start, "(y)") || !strcmp(op2start, "(y)")) return(2); if(isLabel(op1start) || isLabel(op2start)) return(3+i); if(isShortoff(op1start, "x") || isShortoff(op2start, "x")) return(2); if(isShortoff(op1start, "y") || isShortoff(op2start, "y")) return(3); if(isLongoff(op1start, "x") || isLongoff(op2start, "x")) return(3); if(isRelativeAddr(op1start, "y")) return(4); if(strchr(op1start, 'y') || (strchr(op2start, 'y') && !EQUALS(operand, "ldw"))) i++; // costs extra byte for operating with y if(isReg(op1start) && isReg(op2start)) return(1+i); if(op2start[0] == '#') return(2+i); // ld reg, #immd if(readint(op2start) <= 0xFF) return(2+i); return(3+i); } /* mov costs 3, 4 or 5 bytes depending on it's addressing mode */ if(EQUALS(operand, "mov")) { if(op2start && op2start[0] == '#') return(4); if(op2start && isLabel(op2start)) return(5); if(op2start && readint(op2start) <= 0xFF) return(3); if(op2start && readint(op2start) > 0xFF) return(5); } /* Operations that always costs 1 byte */ if(EQUALS(operand, "ccf") || EQUALS(operand, "divw") || EQUALS(operand, "exgw") || EQUALS(operand, "iret") || EQUALS(operand, "nop") || EQUALS(operand, "rcf") || EQUALS(operand, "ret") || EQUALS(operand, "retf") || EQUALS(operand, "rvf") || EQUALS(operand, "scf")) { return(1); } /* Operations that costs 2 or 1 bytes depending on is the Y or X register used */ if(EQUALS(operand, "clrw") || EQUALS(operand, "decw") || EQUALS(operand, "div") || EQUALS(operand, "incw") || EQUALS(operand, "mul") || EQUALS(operand, "negw") || EQUALS(operand, "popw") || EQUALS(operand, "pushw") || EQUALS(operand, "rlcw") || EQUALS(operand, "rlwa") || EQUALS(operand, "rrcw") || EQUALS(operand, "rrwa") || EQUALS(operand, "sllw") || EQUALS(operand, "slaw") || EQUALS(operand, "sraw") || EQUALS(operand, "srlw") || EQUALS(operand, "swapw") || EQUALS(operand, "tnzw")) { if((op1start && !strcmp(op1start, "y")) || (op2start && !strcmp(op2start, "y"))) return(2); else return(1); } return(4); }
int isReg(char* reg_name) { //Test si une chaine de caractere est un registre valide if(reg_name[0]=='$') { return isReg(reg_name+1); //Prise en charge du $ pour les reg } char * string; int index=-1; index = strtol(reg_name,&string,10); //printf("reg_name= %s string =%s, index=%d\n",reg_name,string,index ); if (isdigit(reg_name[0]) && index<NBREG && index > -1) { return index; } else if (!isdigit(reg_name[0])) { if (!strcmp(string,"zero")) { index=0; } else if (!strcmp(string,"at")) { index=1; } else if (!strcmp(string,"v0")) { index=2; } else if (!strcmp(string,"v1")) { index=3; } else if (!strcmp(string,"a0")) { index=4; } else if (!strcmp(string,"a1")) { index=5; } else if (!strcmp(string,"a2")) { index=6; } else if (!strcmp(string,"a3")) { index=7; } else if (!strcmp(string,"t0")) { index=8; } else if (!strcmp(string,"t1")) { index=9; } else if (!strcmp(string,"t2")) { index=10; } else if (!strcmp(string,"t3")) { index=11; } else if (!strcmp(string,"t4")) { index=12; } else if (!strcmp(string,"t5")) { index=13; } else if (!strcmp(string,"t6")) { index=14; } else if (!strcmp(string,"t7")) { index=15; } else if (!strcmp(string,"s0")) { index=16; } else if (!strcmp(string,"s1")) { index=17; } else if (!strcmp(string,"s2")) { index=18; } else if (!strcmp(string,"s3")) { index=19; } else if (!strcmp(string,"s4")) { index=20; } else if (!strcmp(string,"s5")) { index=21; } else if (!strcmp(string,"s6")) { index=22; } else if (!strcmp(string,"s7")) { index=23; } else if (!strcmp(string,"t8")) { index=24; } else if (!strcmp(string,"t9")) { index=25; } else if (!strcmp(string,"k0")) { index=26; } else if (!strcmp(string,"k1")) { index=27; } else if (!strcmp(string,"gp")) { index=28; } else if (!strcmp(string,"sp")) { index=29; } else if (!strcmp(string,"fp")) { index=30; } else if (!strcmp(string,"ra")) { index=31; } else if (!strcmp(string,"HI")) { index=32; } else if (!strcmp(string,"LO")) { index=33; } else if (!strcmp(string,"PC")) { index=34; } else index=-1; return index; } index=-1; return index; }
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; }
bool Operand6502::isNdxReg(char *str, int *reg) { return (isReg(str, reg)); }