static void OneLine (const OpcDesc* D, const char* Arg, ...) /* Output one line with the given mnemonic and argument */ { char Buf [256]; va_list ap; /* Mnemonic */ Mnemonic (D->Mnemo); /* Argument */ va_start (ap, Arg); xvsprintf (Buf, sizeof (Buf), Arg, ap); va_end (ap); Indent (ACol); Output ("%s", Buf); /* Add the code stuff as comment */ LineComment (PC, D->Size); /* End the line */ LineFeed (); }
/** * The algorithm finds conditional instruction (=condInst) first, then * corresponding CMP instruction (=cmpInst) and arithmetic instruction (=inst) * which affects flags in the same way as CMP. Combination is considered as * available to be reduced if there are no instructions between CMP and * arithmetic instruction which influence to flags or CMP operands. * * Also it transforms some conditional instruction to make them more suitable * for optimizations */ void RCE::runImpl() { Inst * inst, * cmpInst, *condInst; Opnd * cmpOp = NULL; cmpInst = condInst = NULL; const Nodes& nodes = irManager->getFlowGraph()->getNodesPostOrder(); for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) { Node* node = *it; if (node->isBlockNode()) { if(node->isEmpty()) { continue; } cmpInst = NULL; Inst* prevInst = NULL; for(inst = (Inst*)node->getLastInst(); inst != NULL; inst = prevInst) { prevInst = inst->getPrevInst(); //find conditional instruction Mnemonic baseMnem = getBaseConditionMnemonic(inst->getMnemonic()); if (baseMnem != Mnemonic_NULL) { condInst = condInst ? NULL : inst; cmpInst = NULL; } else if (condInst) { //find CMP instruction corresponds to conditional instruction if(inst->getMnemonic() == Mnemonic_CMP || inst->getMnemonic() == Mnemonic_UCOMISD || inst->getMnemonic() == Mnemonic_UCOMISS) { if (cmpInst) { //this comparison is redundant because of overrided by cmpInst inst->unlink(); continue; } cmpInst = inst; U_32 defCount = inst->getOpndCount(Inst::OpndRole_InstLevel|Inst::OpndRole_Def); if(inst->getOpnd(defCount+1)->isPlacedIn(OpndKind_Imm)) { //try to change conditional instruction to make combination available to optimize cmpOp = inst->getOpnd(defCount); Inst * newCondInst = NULL; Mnemonic mnem; int64 val = inst->getOpnd(defCount+1)->getImmValue(); if (val == 0) { continue; } else if (val == 1 && ConditionMnemonic(condInst->getMnemonic()-getBaseConditionMnemonic(condInst->getMnemonic())) == ConditionMnemonic_L){ mnem = Mnemonic((condInst->getMnemonic() - Mnemonic(ConditionMnemonic_L)) + Mnemonic(ConditionMnemonic_LE)); } else if (val == -1 && ConditionMnemonic(condInst->getMnemonic()-getBaseConditionMnemonic(condInst->getMnemonic())) == ConditionMnemonic_G) { mnem = Mnemonic((condInst->getMnemonic() - Mnemonic(ConditionMnemonic_G)) + Mnemonic(ConditionMnemonic_GE)); } else if (val == -1 && ConditionMnemonic(condInst->getMnemonic()-getBaseConditionMnemonic(condInst->getMnemonic())) == ConditionMnemonic_B) { mnem = Mnemonic((condInst->getMnemonic() - Mnemonic(ConditionMnemonic_B)) + Mnemonic(ConditionMnemonic_BE)); } else { continue; } //replace old conditional instruction if (condInst->hasKind(Inst::Kind_BranchInst)) { BranchInst* br = (BranchInst*)condInst; newCondInst = irManager->newBranchInst(mnem,br->getTrueTarget(), br->getFalseTarget(), condInst->getOpnd(0)); } else { Mnemonic condMnem = getBaseConditionMnemonic(condInst->getMnemonic()); Inst::Opnds defs(condInst,Inst::OpndRole_Def|Inst::OpndRole_Explicit); if (condMnem == Mnemonic_CMOVcc) { Inst::Opnds uses(condInst,Inst::OpndRole_Use|Inst::OpndRole_Explicit); newCondInst = irManager->newInst(mnem, condInst->getOpnd(defs.begin()), inst->getOpnd(uses.begin())); } else if (condMnem == Mnemonic_SETcc) { newCondInst = irManager->newInst(mnem, condInst->getOpnd(defs.begin())); } else { assert(0); continue; } } newCondInst->insertAfter(condInst); condInst->unlink(); condInst = newCondInst; inst->setOpnd(defCount+1, irManager->newImmOpnd(inst->getOpnd(defCount+1)->getType(),0)); } //find flags affected instruction precedes cmpInst } else if (instAffectsFlagsAsCmpInst(inst, condInst)) { if (cmpInst) { if (isSuitableToRemove(inst, condInst, cmpInst, cmpOp)) { cmpInst->unlink(); } } condInst = NULL; // do not optimize cmpInst any more in this block } else { if (inst->getOpndCount(Inst::OpndRole_Implicit|Inst::OpndRole_Def) || inst->getMnemonic() == Mnemonic_CALL) { // instruction affects flags, skip optimizing cmpInst condInst = NULL; } else { //check for moving cmpInst operands if ((inst->getMnemonic() == Mnemonic_MOV) && (inst->getOpnd(0) == cmpOp)) { cmpOp = inst->getOpnd(1); } } } }//end if/else by condInst }//end for() by Insts }//end if BasicBlock }//end for() by Nodes }