Index: working_vm/vm/port/src/encoder/ia32_em64t/enc_defs.h =================================================================== --- working_vm/vm/port/src/encoder/ia32_em64t/enc_defs.h (revision 671441) +++ working_vm/vm/port/src/encoder/ia32_em64t/enc_defs.h (working copy) @@ -604,12 +604,12 @@ CCM(SET,NLE), CCM(SET,G), Mnemonic_SAL, Mnemonic_SHL=Mnemonic_SAL,// Shift left -Mnemonic_SAR, // Unsigned shift right +Mnemonic_SAR, // Signed shift right Mnemonic_ROR, // Rotate right Mnemonic_RCR, // Rotate right through CARRY flag Mnemonic_ROL, // Rotate left Mnemonic_RCL, // Rotate left through CARRY flag -Mnemonic_SHR, // Signed shift right +Mnemonic_SHR, // Unsigned shift right Mnemonic_SHRD, // Double Precision Shift Right Mnemonic_SHLD, // Double Precision Shift Left Index: working_vm/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp =================================================================== --- working_vm/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (revision 671441) +++ working_vm/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (working copy) @@ -788,6 +788,31 @@ return sub(ArithmeticOp::I4, ref1, ref2); } + +static long long getShiftBits(long long divisor) +{ + bool isPower=false; + int shiftBits=-1; + if(divisor&1==1) { + isPower=true; + shiftBits=0; + } + for(int i=1;i<64;i++) { + divisor>>=1; + if(divisor&1==1) { + if(isPower){ + isPower=false; + shiftBits=-1; + return -1; + } + else { + isPower=true; + shiftBits=i; + } + } + } + return shiftBits; +} //_______________________________________________________________________________________________________________ // Multiply numeric values @@ -798,6 +823,73 @@ { Type * dstType; Opnd * dst, * srcOpnd1, * srcOpnd2; + + //for integer mul op, replace it with left shift if one of the two multipliers is a constant and a power of 2 + int isConst=0; //0-neither 1-src1 2-src2 + long long multiplier=((Opnd*)src1)->getImmValue(); + if(multiplier!=0) + isConst=1; + else { + multiplier=((Opnd*)src2)->getImmValue(); + if(multiplier!=0) + isConst=2; + } + IntegerOp::Types shiftOpType; + + if(isConst!=0) { + switch(opType) { + case ArithmeticOp::I: + case ArithmeticOp::I4: + { + dstType=irManager.getTypeFromTag(Type::Int32); + shiftOpType=IntegerOp::I4; + break; + } + case ArithmeticOp::I8: + { + dstType=irManager.getTypeFromTag(Type::Int64); + shiftOpType=IntegerOp::I8; + break; + } + default: + { + break; + } + } + + if((opType==ArithmeticOp::I)||(opType==ArithmeticOp::I4)||(opType==ArithmeticOp::I8)) { + Opnd * srcOpnd1=(Opnd*)convert(src1, dstType); + Opnd * srcOpnd2=(Opnd*)convert(src2, dstType); + + bool doNegate=false; + if(multiplier<0) { + doNegate=true; + multiplier=-multiplier; + } + + long long shiftBits=getShiftBits(multiplier); + if(shiftBits!=-1) { + Opnd *shiftResult=NULL; + if(isConst==1) { + srcOpnd1->assignImmValue(shiftBits); + shiftResult=shiftOp(shiftOpType, Mnemonic_SHL, srcOpnd2, srcOpnd1); + } + else { + //is_const == 2 + srcOpnd2->assignImmValue(shiftBits); + shiftResult=shiftOp(shiftOpType, Mnemonic_SHL, srcOpnd1, srcOpnd2); + } + if(!doNegate) + return shiftResult; + else { + dst=irManager.newOpnd(dstType); + appendInsts(irManager.newInstEx(Mnemonic_NEG, 1, dst, (Opnd*)convert(shiftResult, dstType))); + return dst; + } + } + } + } + switch(opType){ case ArithmeticOp::I4: case ArithmeticOp::I: @@ -852,6 +944,79 @@ Opnd * dst=NULL; Type * dstType; Opnd * srcOpnd1, * srcOpnd2; + + + //for integer div op, replace it with right shift if the divisor is a constant and a power of 2 + //div: q = a / (1 << d); + //shift: q = (a + [(1 << d) - 1] & (a >> 31)) >> d; + IntegerOp::Types shiftAndOpType; + ArithmeticOp::Types addSubOpType; + int maskShiftBits; + long long divisor=src2->getImmValue(); + if(divisor!=0) { + switch(opType) { + case DivOp::I: + case DivOp::I4: + { + dstType=irManager.getTypeFromTag(Type::Int32); + shiftAndOpType=IntegerOp::I4; + addSubOpType=ArithmeticOp::I4; + maskShiftBits=31; + break; + } + case DivOp::I8: + { + dstType=irManager.getTypeFromTag(Type::Int64); + shiftAndOpType=IntegerOp::I8; + addSubOpType=ArithmeticOp::I8; + maskShiftBits=63; + break; + } + default: + { + break; + } + } + + if((opType==DivOp::I)||(opType==DivOp::I4)||(opType==DivOp::I8)) { + Opnd * srcOpnd1=(Opnd*)convert(src1, dstType); + + bool doNegate=false; + if(divisor<0) { + doNegate=true; + divisor=-divisor; + } + + long long shiftBits=getShiftBits(divisor); + if(shiftBits!=-1) { + Opnd *constMask=irManager.newOpnd(dstType); + constMask->assignImmValue(maskShiftBits); + Opnd *mask=shiftOp(shiftAndOpType, Mnemonic_SAR, srcOpnd1, constMask); + + Opnd *const1=irManager.newOpnd(dstType); + Opnd *shfBits=irManager.newOpnd(dstType); + const1->assignImmValue(1); + shfBits->assignImmValue(shiftBits); + Opnd *power=shiftOp(shiftAndOpType, Mnemonic_SHL, const1, shfBits); + Opnd *span=(Opnd *)sub(addSubOpType, power, const1); + + Opnd *offset=(Opnd *)and_(shiftAndOpType, span, mask); + + Opnd *toBeShifted=(Opnd *)add(addSubOpType, srcOpnd1, offset); + + src2->assignImmValue(shiftBits); + Opnd *shiftResult=shiftOp(shiftAndOpType, Mnemonic_SAR, (Opnd*)toBeShifted, (Opnd*)convert(src2, dstType)); + if(!doNegate) + return shiftResult; + else { + dst=irManager.newOpnd(dstType); + appendInsts(irManager.newInstEx(Mnemonic_NEG, 1, dst, (Opnd*)convert(shiftResult, dstType))); + return dst; + } + } + } + } + switch(opType){ case DivOp::I: case DivOp::I4: