Index: vm/jitrino/src/codegenerator/ia32/Ia32BranchTrans.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32BranchTrans.cpp (revision 633014) +++ vm/jitrino/src/codegenerator/ia32/Ia32BranchTrans.cpp (working copy) @@ -325,10 +325,109 @@ } } - bool cmovs = false; + bool signcheck = false; + getArg("signCheckEliminate", signcheck); + + if (signcheck) { + for (Nodes::const_reverse_iterator it = nodes.rbegin(),end = nodes.rend();it!=end; ++it) { + Node* bb = *it; + if (bb->isBlockNode()){ + if(bb->isEmpty()) + continue; + + Inst * inst = (Inst *)bb->getLastInst(); + //check is last instruction in basic block is a conditional branch instruction + if(inst && inst->hasKind(Inst::Kind_BranchInst)) { + //get successors of bb + if(bb->getOutEdges().size() == 1) + continue; + + Edge * trueEdge = bb->getTrueEdge(); + Edge * falseEdge = bb->getFalseEdge(); + Node * trueBB = trueEdge->getTargetNode(); + Node * falseBB = falseEdge->getTargetNode(); + + Inst * trueInst = (Inst *)trueBB->getFirstInst(); + Inst * falseInst = (Inst *)falseBB->getFirstInst(); + Inst * prevInst = inst->getPrevInst(); + + if (prevInst && falseInst) + { + uint32 prevDefCount = prevInst->getOpndCount(Inst::OpndRole_InstLevel|Inst::OpndRole_Def); + uint32 falseDefCount = falseInst->getOpndCount(Inst::OpndRole_InstLevel|Inst::OpndRole_Def); + Inst * nextFalse = falseInst->getNextInst(); + + // check if we have following in current BB: + // cmp x, 0 + // jge trueBB + if ( prevInst->getMnemonic() == Mnemonic_CMP && inst->getMnemonic() == Mnemonic_JGE && + prevInst->getOpnd(prevDefCount+1)->isPlacedIn(OpndKind_Imm) && prevInst->getOpnd(prevDefCount+1)->getImmValue() == 0) { + + // check if we have following in false BB: + // w = add x, y + if ( falseInst->getMnemonic() == Mnemonic_ADD && + falseInst->getOpnd(falseDefCount) == prevInst->getOpnd(prevDefCount)) { + + // check if that was the only instruction in false BB or there was also + // mov v, w + if ( falseBB->getInstCount() == 1 || (falseBB->getInstCount() == 2 && + nextFalse->getMnemonic() == Mnemonic_MOV && + nextFalse->getOpnd(1) == falseInst->getOpnd(0)) ) { + + //check if trueBB is successor of falseBB + bool canBeRemoved = true; + Node * nextBB = trueBB; + if (falseBB->getOutEdges().front()->getTargetNode() != nextBB) + canBeRemoved = false; + + //check if bb is the only predecessor of falseBB + const Edges& fEdges = falseBB->getInEdges(); + for (Edges::const_iterator edge = fEdges.begin(); edge != fEdges.end(); ++edge) { + Edge * e = *edge; + if (e->getSourceNode() != bb) + canBeRemoved = false; + } + if (!canBeRemoved) + continue; + + // eliminating branch + + if (nextFalse) + nextFalse->unlink(); + + Opnd* x = prevInst->getOpnd(prevDefCount); + Opnd* tmp = irManager->newOpnd(x->getType()); + // mov tmp, x + bb->appendInst(irManager->newCopyPseudoInst(Mnemonic_MOV, tmp, x)); + // sar tmp, 31 (spreading sign for the whole register) + bb->appendInst(irManager->newInstEx(Mnemonic_SAR, 1, tmp, tmp, irManager->newImmOpnd(irManager->getTypeManager().getInt8Type(), 31))); + // and tmp, y + bb->appendInst(irManager->newInstEx(Mnemonic_AND, 1, tmp, tmp, falseInst->getOpnd(falseDefCount+1))); + // add w, tmp + bb->appendInst(irManager->newInstEx(Mnemonic_ADD, 1, falseInst->getOpnd(0), x, tmp)); + if (nextFalse) + bb->appendInst(nextFalse); + + irManager->getFlowGraph()->removeEdge(trueEdge); + irManager->getFlowGraph()->removeEdge(falseEdge); + irManager->getFlowGraph()->addEdge(bb, nextBB); + irManager->getFlowGraph()->removeNode(falseBB); + prevInst->unlink(); + inst->unlink(); + } + } + } + } + + }//end if BasicBlock + }//end for() by Nodes + } + } + + bool cmovs = false; getArg("insertCMOVs", cmovs); - if (cmovs) { + if (cmovs) { for (Nodes::const_reverse_iterator it = nodes.rbegin(),end = nodes.rend();it!=end; ++it) { Node* bb = *it; if (bb->isBlockNode()){ @@ -342,14 +441,16 @@ if(bb->getOutEdges().size() == 1) continue; - Node * trueBB = bb->getTrueEdge()->getTargetNode(); - Node * falseBB = bb->getFalseEdge()->getTargetNode(); + Edge * trueEdge = bb->getTrueEdge(); + Edge * falseEdge = bb->getFalseEdge(); + Node * trueBB = trueEdge->getTargetNode(); + Node * falseBB = falseEdge->getTargetNode(); ConditionMnemonic condMnem = ConditionMnemonic(inst->getMnemonic() - getBaseConditionMnemonic(inst->getMnemonic())); - //check is both successors have only instruction Inst * trueInst = (Inst *)trueBB->getFirstInst(); Inst * falseInst = (Inst *)falseBB->getFirstInst(); + Inst * prevInst = inst->getPrevInst(); if(trueBB && falseInst && trueBB->getInstCount() == 1 && falseBB->getInstCount() == 1 && trueInst->getMnemonic() == Mnemonic_MOV && falseInst->getMnemonic() == Mnemonic_MOV && trueInst->getOpnd(0) == falseInst->getOpnd(0) && trueInst->getOpnd(0)->getMemOpndKind() == MemOpndKind_Null) { //check is bb is only predecessor for trueBB and falseBB bool canBeRemoved = true; @@ -401,7 +502,6 @@ inst->unlink(); irManager->getFlowGraph()->removeNode(falseBB); irManager->getFlowGraph()->removeNode(trueBB); - } } }//end if BasicBlock