Index: vm/port/src/encoder/ia32_em64t/enc_tabl.cpp =================================================================== --- vm/port/src/encoder/ia32_em64t/enc_tabl.cpp (revision 490281) +++ vm/port/src/encoder/ia32_em64t/enc_tabl.cpp (working copy) @@ -478,11 +478,11 @@ END_MNEMONIC() #define DEFINE_CMOVcc_MNEMONIC( cc ) \ - BEGIN_MNEMONIC(CMOV##cc, MF_USES_FLAGS|MF_CONDITIONAL, D_U ) \ + BEGIN_MNEMONIC(CMOV##cc, MF_USES_FLAGS|MF_CONDITIONAL, DU_U ) \ BEGIN_OPCODES() \ - {OpcodeInfo::all, {Size16, 0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r16, r_m16}, D_U }, \ - {OpcodeInfo::all, {0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r32, r_m32}, D_U }, \ - {OpcodeInfo::em64t, {REX_W, 0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r64, r_m64}, D_U }, \ + {OpcodeInfo::all, {Size16, 0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r16, r_m16}, DU_U }, \ + {OpcodeInfo::all, {0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r32, r_m32}, DU_U }, \ + {OpcodeInfo::em64t, {REX_W, 0x0F, 0x40 + ConditionMnemonic_##cc, _r}, {r64, r_m64}, DU_U }, \ END_OPCODES() \ END_MNEMONIC() @@ -1108,9 +1108,9 @@ END_MNEMONIC() #define DEFINE_SETcc_MNEMONIC( cc ) \ - BEGIN_MNEMONIC(SET##cc, MF_USES_FLAGS|MF_CONDITIONAL, D) \ + BEGIN_MNEMONIC(SET##cc, MF_USES_FLAGS|MF_CONDITIONAL, DU) \ BEGIN_OPCODES() \ - {OpcodeInfo::all, {0x0F, 0x90 + ConditionMnemonic_##cc}, {r_m8}, D }, \ + {OpcodeInfo::all, {0x0F, 0x90 + ConditionMnemonic_##cc}, {r_m8}, DU }, \ END_OPCODES() \ END_MNEMONIC() Index: vm/jitrino/config/ia32/server_static.emconf =================================================================== --- vm/jitrino/config/ia32/server_static.emconf (revision 490281) +++ vm/jitrino/config/ia32/server_static.emconf (working copy) @@ -25,7 +25,7 @@ -XDjit.SS_OPT.path=opt_init,translator,optimizer,hir2lir,codegen -XDjit.SS_OPT.path.optimizer=ssa,simplify,dce,uce,statprof,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals --XDjit.SS_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method +-XDjit.SS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.SS_OPT.path.dce1=cg_dce -XDjit.SS_OPT.path.dce2=cg_dce -XDjit.SS_OPT.path.regalloc=bp_regalloc1,bp_regalloc2 @@ -40,6 +40,8 @@ -XDjit.SS_OPT.arg.codegen.dce1.early=yes -XDjit.SS_OPT.arg.codegen.regalloc.bp_regalloc1.regs=ALL_GP -XDjit.SS_OPT.arg.codegen.regalloc.bp_regalloc2.regs=ALL_XMM +-XDjit.SS_OPT.arg.codegen.btr.insertCMOVs=no +-XDjit.SS_OPT.arg.codegen.btr.removeConstCompare=yes #system properties Index: vm/jitrino/config/ia32/client.emconf =================================================================== --- vm/jitrino/config/ia32/client.emconf (revision 490281) +++ vm/jitrino/config/ia32/client.emconf (working copy) @@ -54,7 +54,7 @@ -XDjit.CD_OPT.path=opt_init,translator,optimizer,hir2lir,codegen -XDjit.CD_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals --XDjit.CD_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method +-XDjit.CD_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.CD_OPT.path.dce1=cg_dce -XDjit.CD_OPT.path.dce2=cg_dce -XDjit.CD_OPT.path.regalloc=bp_regalloc1,bp_regalloc2 @@ -69,6 +69,8 @@ -XDjit.CD_OPT.arg.codegen.dce1.early=yes -XDjit.CD_OPT.arg.codegen.regalloc.bp_regalloc1.regs=ALL_GP -XDjit.CD_OPT.arg.codegen.regalloc.bp_regalloc2.regs=ALL_XMM +-XDjit.CD_OPT.arg.codegen.btr.insertCMOVs=no +-XDjit.CD_OPT.arg.codegen.btr.removeConstCompare=yes #system properties Index: vm/jitrino/config/ia32/opt.emconf =================================================================== --- vm/jitrino/config/ia32/opt.emconf (revision 490281) +++ vm/jitrino/config/ia32/opt.emconf (working copy) @@ -25,7 +25,7 @@ -XDjit.CS_OPT.path=opt_init,translator,optimizer,hir2lir,codegen -XDjit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals --XDjit.CS_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method +-XDjit.CS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.CS_OPT.path.dce1=cg_dce -XDjit.CS_OPT.path.dce2=cg_dce -XDjit.CS_OPT.path.regalloc=bp_regalloc1,bp_regalloc2 @@ -42,6 +42,9 @@ -XDjit.CS_OPT.arg.codegen.regalloc.bp_regalloc1.regs=ALL_GP -XDjit.CS_OPT.arg.codegen.regalloc.bp_regalloc2.regs=ALL_XMM +-XDjit.CS_OPT.arg.codegen.btr.insertCMOVs=no +-XDjit.CS_OPT.arg.codegen.btr.removeConstCompare=yes + #-XDjit.CS_OPT.arg.log.irdump.file=log/%jit%/%log%/%seqnb%_%class%.%method%.log #-XDjit.CS_OPT.arg.log=ct,ir,irdump,all Index: vm/jitrino/config/ia32/server.emconf =================================================================== --- vm/jitrino/config/ia32/server.emconf (revision 490281) +++ vm/jitrino/config/ia32/server.emconf (working copy) @@ -46,7 +46,7 @@ -XDjit.SD1_OPT.path=opt_init,translator,optimizer,hir2lir,codegen -XDjit.SD1_OPT.path.optimizer=ssa,simplify,dce,uce,vp_instrument,edge_instrument,dessa,statprof,markglobals --XDjit.SD1_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method +-XDjit.SD1_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.SD1_OPT.path.dce1=cg_dce -XDjit.SD1_OPT.path.dce2=cg_dce -XDjit.SD1_OPT.path.regalloc=bp_regalloc1,bp_regalloc2 @@ -56,11 +56,13 @@ -XDjit.SD1_OPT.arg.codegen.dce1.early=yes -XDjit.SD1_OPT.arg.codegen.regalloc.bp_regalloc1.regs=ALL_GP -XDjit.SD1_OPT.arg.codegen.regalloc.bp_regalloc2.regs=ALL_XMM +-XDjit.SD1_OPT.arg.codegen.btr.insertCMOVs=no +-XDjit.SD1_OPT.arg.codegen.btr.removeConstCompare=yes -XDjit.SD2_OPT.path=opt_init,translator,optimizer,hir2lir,codegen -XDjit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,edge_annotate,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,abcd,dce,uce,gcm,dessa,statprof,markglobals --XDjit.SD2_OPT.path.codegen=lock_method,bbp,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method +-XDjit.SD2_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,layout,copy,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method -XDjit.SD2_OPT.path.dce1=cg_dce -XDjit.SD2_OPT.path.dce2=cg_dce -XDjit.SD2_OPT.path.regalloc=bp_regalloc1,bp_regalloc2 @@ -102,6 +104,8 @@ -XDjit.SD2_OPT.arg.codegen.dce1.early=yes -XDjit.SD2_OPT.arg.codegen.regalloc.bp_regalloc1.regs=ALL_GP -XDjit.SD2_OPT.arg.codegen.regalloc.bp_regalloc2.regs=ALL_XMM +-XDjit.SD2_OPT.arg.codegen.btr.insertCMOVs=no +-XDjit.SD2_OPT.arg.codegen.btr.removeConstCompare=yes #system properties Index: vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (revision 490281) +++ vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (working copy) @@ -570,7 +570,6 @@ Node* sinkNode = subCFG->getReturnNode(); bbHMain->appendInst(irManager->newInst(Mnemonic_CMP, src1_2, src2_2)); - bbHMain->appendInst(irManager->newBranchInst(Mnemonic_JNZ, sinkNode, bbLMain)); bbLMain->appendInst(irManager->newInst(Mnemonic_CMP, src1_1, src2_1)); @@ -588,7 +587,16 @@ } bbLMain->appendInst(irManager->newBranchInst(mnem, bbDB, bbFT)); - subCFG->addEdge(bbHMain, sinkNode, 0.1); + if (condInst->getMnemonic() == Mnemonic_JZ) { + bbHMain->appendInst(irManager->newBranchInst(Mnemonic_JNZ, bbFT, bbLMain)); + subCFG->addEdge(bbHMain, bbFT, 0.1); + } else if (condInst->getMnemonic() == Mnemonic_JNZ) { + bbHMain->appendInst(irManager->newBranchInst(Mnemonic_JNZ, bbDB, bbLMain)); + subCFG->addEdge(bbHMain, bbDB, 0.1); + } else { + bbHMain->appendInst(irManager->newBranchInst(Mnemonic_JNZ, sinkNode, bbLMain)); + subCFG->addEdge(bbHMain, sinkNode, 0.1); + } subCFG->addEdge(bbHMain, bbLMain, 0.9); subCFG->addEdge(bbLMain, bbFT, 0.1); subCFG->addEdge(bbLMain, bbDB, 0.9); @@ -611,7 +619,7 @@ bbLMain->appendInst(irManager->newInst(Mnemonic_CMP, src1_1, src2_1)); - irManager->getFlowGraph()->splitNodeAtInstruction(condInst, false, true, NULL); + irManager->getFlowGraph()->splitNodeAtInstruction(condInst, true, true, NULL); Mnemonic mnem = getBaseConditionMnemonic(condInst->getMnemonic()); Index: vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp (revision 490281) +++ vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp (working copy) @@ -467,9 +467,15 @@ Opnd* fromOpnd = NULL; int32 offset = 0; Mnemonic mn = inst->getMnemonic(); + + Mnemonic conditionalMnem = getBaseConditionMnemonic(mn); + if (conditionalMnem != Mnemonic_NULL) + mn = conditionalMnem; + switch (mn) { case Mnemonic_XOR: case Mnemonic_MOV: + case Mnemonic_CMOVcc: assert(mn != Mnemonic_XOR || inst->getOpnd(useIndex1)==opnd); fromOpnd = inst->getOpnd(useIndex1); break; Index: vm/jitrino/src/codegenerator/ia32/Ia32APIMagics.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32APIMagics.cpp (revision 490281) +++ vm/jitrino/src/codegenerator/ia32/Ia32APIMagics.cpp (working copy) @@ -149,7 +149,7 @@ irm->newCopyPseudoInst(Mnemonic_MOV, r2, irm->newImmOpnd(i32Type, -1))->insertBefore(callInst); irm->newInstEx(Mnemonic_BSR, 1, r1, arg)->insertBefore(callInst); - irm->newInstEx(Mnemonic_CMOVZ, 1, r1, r2)->insertBefore(callInst); + irm->newInstEx(Mnemonic_CMOVZ, 1, r1, r1, r2)->insertBefore(callInst); irm->newInstEx(Mnemonic_SUB, 1, res, irm->newImmOpnd(i32Type, 31), r1)->insertBefore(callInst); callInst->unlink(); @@ -168,7 +168,7 @@ irm->newCopyPseudoInst(Mnemonic_MOV, r2, irm->newImmOpnd(i32Type, 32))->insertBefore(callInst); irm->newInstEx(Mnemonic_BSF, 1, r1, arg)->insertBefore(callInst); - irm->newInstEx(Mnemonic_CMOVZ, 1, r1, r2)->insertBefore(callInst); + irm->newInstEx(Mnemonic_CMOVZ, 1, r1, r1, r2)->insertBefore(callInst); irm->newCopyPseudoInst(Mnemonic_MOV, res, r1)->insertBefore(callInst); callInst->unlink(); @@ -219,7 +219,7 @@ //high_part_is_zero hiZeroNode->appendInst(irm->newCopyPseudoInst(Mnemonic_MOV, r2, irm->newImmOpnd(i32Type, -1))); hiZeroNode->appendInst(irm->newInstEx(Mnemonic_BSR, 1, r1, lwOpnd)); - hiZeroNode->appendInst(irm->newInstEx(Mnemonic_CMOVZ, 1, r1, r2)); + hiZeroNode->appendInst(irm->newInstEx(Mnemonic_CMOVZ, 1, r1, r1, r2)); hiZeroNode->appendInst(irm->newInstEx(Mnemonic_SUB, 1, res, irm->newImmOpnd(i32Type, 63), r1)); @@ -297,3 +297,4 @@ } }} //namespace + Index: vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (revision 490281) +++ vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (working copy) @@ -1009,7 +1009,7 @@ Opnd * srcOpnd=convert(src, dstType); appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dst, (Opnd*)srcOpnd)); appendInsts(irManager.newInst(Mnemonic_NEG, dst)); - appendInsts(irManager.newInstEx(Mnemonic_CMOVL, 1, dst, (Opnd*)srcOpnd)); + appendInsts(irManager.newInstEx(Mnemonic_CMOVL, 1, dst, dst, (Opnd*)srcOpnd)); break; } case NegOp::I8: @@ -1219,10 +1219,10 @@ if (swapped) cm=swapConditionMnemonic(cm); appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 0))); - appendInsts(irManager.newInstEx(getMnemonic(Mnemonic_SETcc, cm), 1, dst)); + appendInsts(irManager.newInstEx(getMnemonic(Mnemonic_SETcc, cm), 1, dst,dst)); #ifndef _EM64T_ if (((opType==CompareOp::F) ||(opType==CompareOp::S) ||(opType==CompareOp::D)) && ((cmpOp == CompareOp::Geu) || (cmpOp == CompareOp::Gtu))) { - appendInsts(irManager.newInstEx(Mnemonic_CMOVP,1,dst,irManager.newImmOpnd(typeManager.getInt32Type(), 0))); + appendInsts(irManager.newInstEx(Mnemonic_CMOVP,1,dst,dst,irManager.newImmOpnd(typeManager.getInt32Type(), 0))); } #endif return dst; @@ -1238,7 +1238,7 @@ cmpToEflags(CompareOp::Eq, getCompareOpTypesFromCompareZeroOpTypes(opType), (Opnd*)src, NULL); appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 0))); - appendInsts(irManager.newInstEx(Mnemonic_CMOVZ, 1, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 1))); + appendInsts(irManager.newInstEx(Mnemonic_CMOVZ, 1, dst, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 1))); return dst; } @@ -1251,7 +1251,7 @@ Opnd * dst=irManager.newOpnd(typeManager.getInt32Type()); cmpToEflags(CompareOp::Eq, getCompareOpTypesFromCompareZeroOpTypes(opType), (Opnd*)src, NULL); appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 0))); - appendInsts(irManager.newInstEx(Mnemonic_CMOVNZ, 1, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 1))); + appendInsts(irManager.newInstEx(Mnemonic_CMOVNZ, 1, dst, dst,irManager.newImmOpnd(typeManager.getInt32Type(), 1))); return dst; } @@ -2809,15 +2809,15 @@ Opnd* ecxOpnd = irManager.getRegOpnd(RegName_ECX); Opnd* memOpnd = irManager.newMemOpnd(opnds[0]->getType(), opnds[0]); - appendInsts(irManager.newInst(Mnemonic_MOV, eaxOpnd, opnds[1])); - appendInsts(irManager.newInst(Mnemonic_MOV, ecxOpnd, opnds[2])); + appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, eaxOpnd, opnds[1])); + appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, ecxOpnd, opnds[2])); Inst* inst = irManager.newInst(Mnemonic_CMPXCHG, memOpnd, ecxOpnd, eaxOpnd); inst->setPrefix(InstPrefix_LOCK); appendInsts(inst); //save the result - appendInsts(irManager.newInst(Mnemonic_MOV, dstOpnd, irManager.newImmOpnd(typeManager.getInt32Type(), 0))); + appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dstOpnd, irManager.newImmOpnd(typeManager.getInt32Type(), 0))); appendInsts(irManager.newInst(Mnemonic_SETZ, dstOpnd)); break; } @@ -3138,7 +3138,7 @@ Opnd * dst=irManager.newOpnd(type); cmpToEflags(CompareOp::Eq, CompareOp::Ref, (Opnd*)instanceOfResult, NULL); appendInsts(irManager.newCopyPseudoInst(Mnemonic_MOV, dst, irManager.newImmOpnd(typeManager.getInt32Type(), 0))); - appendInsts(irManager.newInstEx(Mnemonic_CMOVZ, 1, dst, (Opnd*)obj)); + appendInsts(irManager.newInstEx(Mnemonic_CMOVZ, 1, dst, dst, (Opnd*)obj)); return dst; } Index: vm/jitrino/src/codegenerator/ia32/Ia32BranchTrans.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32BranchTrans.cpp (revision 0) +++ vm/jitrino/src/codegenerator/ia32/Ia32BranchTrans.cpp (revision 0) @@ -0,0 +1,411 @@ +/** + * @author Nikolay A. Sidelnikov + * @version $Revision: 1.6 $ + */ +#include "Ia32IRManager.h" + +namespace Jitrino +{ +namespace Ia32 { +//======================================================================================== +// class BranchTranslator +//======================================================================================== +/** + * class BranchTranslator is implementation of replacing branching for a + * single loading of an operand with a conditional CMOVcc or SETcc + * instruction + * The algorithm takes one-pass over CFG. + * + * This transformer allows to reduce count of branches + * + * This transformer is recommended to be inserted before all optimizations + * because it unites basic blocks + * + * The algorithm works as follows: + * + * 1) Finds branch instruction which performs branch to basic blocks with + * only instructions MOV with the same def-operand. + * + * 2) If each of thus blocks has only one predecessor they and branch + * instruction is replaced with conditional instruction + * + * The implementation of this transformer is located Ia32BranchTrans.cpp. + */ +class BranchTranslator : public SessionAction { + + void runImpl(); +}; + +static ActionFactory _btr("btr"); + +Opnd * getMOVsChainSource(Opnd * opnd) { + + if (opnd->getDefScope() == Opnd::DefScope_SemiTemporary) + return opnd; + + Inst * instUp = opnd->getDefiningInst(); + Inst * movInst = NULL; + + for(;instUp!=NULL && instUp->getMnemonic() == Mnemonic_MOV;instUp = instUp->getOpnd(1)->getDefiningInst()) + { + movInst = instUp; + } + if (movInst) + return movInst->getOpnd(1); + else + return opnd; +} + +bool branchDirection (int64 v1, int64 v2, OpndSize sz,ConditionMnemonic mn) { + switch (sz) { + case OpndSize_8: + v1 = int64(int8(v1)); + v2 = int64(int8(v2)); + break; + case OpndSize_16: + v1 = int64(int16(v1)); + v2 = int64(int16(v2)); + break; + case OpndSize_32: + v1 = int64(int32(v1)); + v2 = int64(int32(v2)); + break; + default: + break; + } + + bool branchDirection = false; + switch (mn) { + case ConditionMnemonic_E: + branchDirection = v1 == v2; + break; + case ConditionMnemonic_NE: + branchDirection = v1 != v2; + break; + case ConditionMnemonic_G: + branchDirection = v1 > v2; + break; + case ConditionMnemonic_GE: + branchDirection = v1>= v2; + break; + case ConditionMnemonic_L: + branchDirection = v1 < v2; + break; + case ConditionMnemonic_LE: + branchDirection = v1 <= v2; + break; + case ConditionMnemonic_AE: + branchDirection = (uint64)v1 >= (uint64)v2; + break; + case ConditionMnemonic_A: + branchDirection = (uint64)v1 > (uint64)v2; + break; + case ConditionMnemonic_BE: + branchDirection = (uint64)v1<= (uint64)v2; + break; + case ConditionMnemonic_B: + branchDirection = (uint64)v1 < (uint64)v2; + break; + default: + assert(0); + break; + } + return branchDirection; +} + +void +BranchTranslator::runImpl() +{ + const Nodes& nodes = irManager->getFlowGraph()->getNodesPostOrder(); + irManager->calculateOpndStatistics(); + + bool consts = false; + getArg("removeConstCompare", consts); + + if (consts) { + StlMap loopHeaders(irManager->getMemoryManager()); + LoopTree * lt = irManager->getFlowGraph()->getLoopTree(); + for (Nodes::const_reverse_iterator it = nodes.rbegin(),end = nodes.rend();it!=end; ++it) { + Node* bb = *it; + if (lt->isLoopHeader(bb)) + loopHeaders[bb] = true; + else + loopHeaders[bb] = false; + } + + 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; + + Node * trueBB = bb->getTrueEdge()->getTargetNode(); + Node * falseBB = bb->getFalseEdge()->getTargetNode(); + + ConditionMnemonic condMnem = ConditionMnemonic(inst->getMnemonic() - getBaseConditionMnemonic(inst->getMnemonic())); + + //****start check for constants comparison**** + + Inst * cmpInst = inst->getPrevInst(); + if (cmpInst && cmpInst->getMnemonic() == Mnemonic_CMP) { + Inst::Opnds uses(cmpInst,Inst::OpndRole_Use|Inst::OpndRole_Explicit|Inst::OpndRole_Auxilary); + Opnd * cmpOp1 = cmpInst->getOpnd(uses.begin()); + Opnd * cmpOp2 = cmpInst->getOpnd(uses.begin()+1); + + if (cmpOp1->getDefScope() == Opnd::DefScope_Temporary) { + cmpOp1 = getMOVsChainSource(cmpOp1); + if (!cmpOp1->isPlacedIn(OpndKind_Imm)) { + for(Inst * copy = (Inst *)bb->getLastInst();copy!=NULL; copy=copy->getPrevInst()) { + Inst::Opnds opnds(copy, Inst::OpndRole_Def|Inst::OpndRole_ForIterator); + for (Inst::Opnds::iterator ito = opnds.begin(); ito != opnds.end(); ito = opnds.next(ito)){ + Opnd * opnd = copy->getOpnd(ito); + if (opnd == cmpOp1 && copy->getMnemonic() == Mnemonic_MOV) { + cmpOp1 = copy->getOpnd(1); + } else { + break; + } + } + } + } + if (cmpOp1->isPlacedIn(OpndKind_Imm)) { + cmpOp2 = getMOVsChainSource(cmpOp2); + if (cmpOp2->isPlacedIn(OpndKind_Imm)) { + //Two constants are operands of CMP inst + irManager->resolveRuntimeInfo(cmpOp1); + irManager->resolveRuntimeInfo(cmpOp2); + int64 v1 = cmpOp1->getImmValue(); + int64 v2 = cmpOp2->getImmValue(); + //remove "dead" edges + if (branchDirection(v1,v2,cmpOp1->getSize(),condMnem)) { + irManager->getFlowGraph()->removeEdge(bb->getFalseEdge()); + } else { + irManager->getFlowGraph()->removeEdge(bb->getTrueEdge()); + } + //remove CMP and Jcc instructions + inst->unlink(); + cmpInst->unlink(); + continue; + } + } + } + cmpOp1 = getMOVsChainSource(cmpOp1); + if (cmpOp1->getDefScope() == Opnd::DefScope_Variable) { + if(loopHeaders[bb]) + continue; + cmpOp2 = getMOVsChainSource(cmpOp2); + if (cmpOp2->isPlacedIn(OpndKind_Imm) && bb->getInEdges().size()>1) { + + const Edges& inEdges = bb->getInEdges(); + StlMap defInsts(irManager->getMemoryManager()); + Inst * nextInst = inst->getPrevInst(); + int i = -1; + bool stopSearch = false; + Node * node = bb; + + while (!stopSearch && i != (int)inEdges.size()) { + bool found = false; + for (Inst * prevInst=NULL; nextInst!=NULL && !found; nextInst=prevInst){ + Inst::Opnds opnds(nextInst, Inst::OpndRole_Def|Inst::OpndRole_ForIterator); + if (i==-1 && nextInst != cmpInst && nextInst->getMnemonic() != Mnemonic_MOV) { + stopSearch = true; + break; + } + for (Inst::Opnds::iterator ito = opnds.begin(); ito != opnds.end(); ito = opnds.next(ito)){ + Opnd * opnd = nextInst->getOpnd(ito); + if (opnd == cmpOp1) { + opnd = getMOVsChainSource(nextInst->getOpnd(1)); + if(!opnd->isPlacedIn(OpndKind_Imm)) { + found=true; + break; + } + if (i==-1) { + stopSearch=true; + break; + } + defInsts[inEdges[i]] = opnd; + found = true; + } + } + prevInst=nextInst->getPrevInst(); + } + const Edges& edges = node->getInEdges(); + if (found || i == -1 || edges.size() > 1) { + i++; + if (i < (int)inEdges.size()) { + node = inEdges[i]->getSourceNode(); + nextInst = (Inst *)node->getLastInst(); + } + } else { + node = edges.front()->getSourceNode(); + nextInst = (Inst*)node->getLastInst(); + } + } + if (!stopSearch) { + for (StlMap::iterator eit = defInsts.begin(); eit != defInsts.end(); eit++) { + Edge * edge = eit->first; + Opnd * opnd = eit->second; + if (branchDirection(opnd->getImmValue(), cmpOp2->getImmValue(),cmpOp1->getSize(),condMnem)) { + irManager->getFlowGraph()->replaceEdgeTarget(edge, trueBB); + } else { + irManager->getFlowGraph()->replaceEdgeTarget(edge, falseBB); + } + for(Inst * copy = (Inst *)bb->getFirstInst();copy!=NULL; copy=copy->getNextInst()) { + if (copy != inst && copy !=cmpInst) { + Node * sourceBB = edge->getSourceNode(); + Inst * lastInst = (Inst*)sourceBB->getLastInst(); + Inst * newInst = copy->getKind() == Inst::Kind_I8PseudoInst? + irManager->newI8PseudoInst(Mnemonic_MOV,1,copy->getOpnd(0),copy->getOpnd(1)): + irManager->newCopyPseudoInst(Mnemonic_MOV,copy->getOpnd(0),copy->getOpnd(1)); + if (lastInst->getKind()== Inst::Kind_BranchInst) + sourceBB->prependInst(newInst, lastInst); + else + sourceBB->appendInst(newInst); + } + } + } + } + } + } else if (cmpOp1->getDefScope() == Opnd::DefScope_SemiTemporary) { + //try to reduce ObjMonitorEnter pattern + const Edges& inEdges = bb->getInEdges(); + if (inEdges.size() != 1) + continue; + Inst * defInst = cmpInst->getPrevInst(); + bool stopSearch = false; + while (1) { + if (!defInst || (defInst->getPrevInst() == NULL && defInst->getNode() == bb)) { + defInst = (Inst*)inEdges.front()->getSourceNode()->getLastInst(); + } else { + defInst = defInst->getPrevInst(); + if (defInst == NULL) + break; + } + Inst::Opnds defs(defInst,Inst::OpndRole_Def|Inst::OpndRole_Explicit|Inst::OpndRole_Auxilary); + for (Inst::Opnds::iterator ito = defs.begin(); ito != defs.end(); ito = defs.next(ito)){ + Opnd * opnd = defInst->getOpnd(ito); + if (opnd == cmpOp1) { + Mnemonic mnem = getBaseConditionMnemonic(defInst->getMnemonic()); + ConditionMnemonic cm = ConditionMnemonic(defInst->getMnemonic()-mnem); + if (mnem == Mnemonic_SETcc && cmpOp2->isPlacedIn(OpndKind_Imm) && cmpOp2->getImmValue() == 0) { + if(cm == (inst->getMnemonic()- getBaseConditionMnemonic(inst->getMnemonic()))) { + defInst->unlink(); + cmpInst->unlink(); + inst->unlink(); + bb->appendInst(irManager->newBranchInst((Mnemonic)(Mnemonic_Jcc+reverseConditionMnemonic(cm)),((BranchInst*)inst)->getTrueTarget(),((BranchInst*)inst)->getFalseTarget())); + stopSearch = true; + break; + } + } else { + stopSearch = true; + break; + } + } + } + Inst::Opnds flags(defInst,Inst::OpndRole_Def|Inst::OpndRole_Implicit); + if (stopSearch || (defInst->getOpnd(flags.begin())->getRegName() == RegName_EFLAGS)) break; + } + continue; + } + } + //****end check for constants comparison**** + } + } + } + } + + bool cmovs = false; + getArg("insertCMOVs", cmovs); + + if (cmovs) { + 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; + + Node * trueBB = bb->getTrueEdge()->getTargetNode(); + Node * falseBB = bb->getFalseEdge()->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(); + 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; + Node * nextBB = trueBB->getOutEdges().front()->getTargetNode(); + if (falseBB->getOutEdges().front()->getTargetNode() != nextBB) + canBeRemoved = false; + + const Edges& tEdges = trueBB->getInEdges(); + for (Edges::const_iterator edge = tEdges.begin(); edge != tEdges.end(); ++edge) { + Edge * e = *edge; + if (e->getSourceNode() != bb) + canBeRemoved = false; + } + 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; + + Opnd * tfOp= trueInst->getOpnd(0); + Opnd * tsOp= trueInst->getOpnd(1); + Opnd * fsOp= falseInst->getOpnd(1); + int64 v1 = tsOp->getImmValue(); + int64 v2 = fsOp->getImmValue(); + if (tsOp->isPlacedIn(OpndKind_Imm) && + fsOp->isPlacedIn(OpndKind_Imm) && + ((v1==0 && v2==1)|| (v1==1 && v2==0))) + { + bb->prependInst(irManager->newCopyPseudoInst(Mnemonic_MOV, tfOp, v1?fsOp:tsOp), inst); + bb->prependInst(irManager->newInstEx(Mnemonic(Mnemonic_SETcc+(v1?condMnem:reverseConditionMnemonic(condMnem))), 1, tfOp,tfOp),inst); + } else { + //insert loading of initial value for operand + bb->prependInst(irManager->newCopyPseudoInst(Mnemonic_MOV, tfOp, fsOp), inst); + if (tsOp->isPlacedIn(OpndKind_Imm)) { + Opnd * tempOpnd = irManager->newOpnd(tsOp->getType()); + Inst * tempInst = irManager->newCopyPseudoInst(Mnemonic_MOV, tempOpnd, tsOp); + bb->prependInst(tempInst, inst); + tsOp = tempOpnd; + } + //insert conditional CMOVcc instruction + bb->prependInst(irManager->newInstEx(Mnemonic(Mnemonic_CMOVcc+condMnem), 1, tfOp,tfOp,tsOp),inst); + } + //link bb with successor of trueBB and falseBB + irManager->getFlowGraph()->replaceEdgeTarget(bb->getFalseEdge(), nextBB); + irManager->getFlowGraph()->removeEdge(bb->getTrueEdge()); + inst->unlink(); + irManager->getFlowGraph()->removeNode(falseBB); + irManager->getFlowGraph()->removeNode(trueBB); + + } + } + }//end if BasicBlock + }//end for() by Nodes + } + + irManager->getFlowGraph()->purgeEmptyNodes(); + irManager->getFlowGraph()->purgeUnreachableNodes(); +} + +} //end namespace Ia32 +} Index: vm/jitrino/src/dynopt/ValueProfiler.cpp =================================================================== --- vm/jitrino/src/dynopt/ValueProfiler.cpp (revision 490281) +++ vm/jitrino/src/dynopt/ValueProfiler.cpp (working copy) @@ -99,7 +99,7 @@ Log::out() << std::endl; } } else { - assert(0); + continue; } VectorHandler* bc2HIRMapHandler = new VectorHandler(bcOffset2HIRHandlerName, &md); uint64 callInstId = (uint64)lastInst->getId();