From 08df4b3da75366e5db37e696eaa7e855cba01deb Mon Sep 17 00:00:00 2001 From: Zheng Xu Date: Tue, 25 Mar 2014 14:25:52 +0000 Subject: [PATCH] Optimize easy multiply and easy div remainder. Update OpRegRegShift and OpRegRegRegShift to use RegStorage parameters. Add special cases for *0 and *1. Add more easy multiply special cases for Arm. Reuse easy multiply in SmallLiteralDivRem() to support remainder cases. Change-Id: Icd76a993d3ac8d4988e9653c19eab4efca14fad0 --- compiler/dex/quick/arm/codegen_arm.h | 15 +++- compiler/dex/quick/arm/int_arm.cc | 146 ++++++++++++++++++++++++++++----- compiler/dex/quick/arm/utility_arm.cc | 49 +++++------ compiler/dex/quick/gen_common.cc | 25 +++++- compiler/dex/quick/mips/codegen_mips.h | 3 +- compiler/dex/quick/mips/int_mips.cc | 5 ++ compiler/dex/quick/mir_to_lir.h | 1 + compiler/dex/quick/x86/codegen_x86.h | 3 +- compiler/dex/quick/x86/int_x86.cc | 5 ++ 9 files changed, 199 insertions(+), 53 deletions(-) diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 0f1e17141..6df341bd9 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -22,13 +22,14 @@ namespace art { -class ArmMir2Lir : public Mir2Lir { +class ArmMir2Lir FINAL : public Mir2Lir { public: ArmMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); // Required for target - codegen helpers. bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, RegLocation rl_dest, int lit); + bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; LIR* CheckSuspendUsingLoad() OVERRIDE; RegStorage LoadHelper(ThreadOffset offset); LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size, @@ -181,8 +182,9 @@ class ArmMir2Lir : public Mir2Lir { LIR* LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size, int s_reg); LIR* StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, OpSize size); - LIR* OpRegRegRegShift(OpKind op, int r_dest, int r_src1, int r_src2, int shift); - LIR* OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, int shift); + LIR* OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2, + int shift); + LIR* OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, int shift); static const ArmEncodingMap EncodingMap[kArmLast]; int EncodeShift(int code, int amount); int ModifiedImmediate(uint32_t value); @@ -202,6 +204,13 @@ class ArmMir2Lir : public Mir2Lir { RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, bool is_div, bool check_zero); RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div); + typedef struct { + OpKind op; + uint32_t shift; + } EasyMultiplyOp; + bool GetEasyMultiplyOp(int lit, EasyMultiplyOp* op); + bool GetEasyMultiplyTwoOps(int lit, EasyMultiplyOp* ops); + void GenEasyMultiplyTwoOps(RegStorage r_dest, RegStorage r_src, EasyMultiplyOp* ops); }; } // namespace art diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index 46db46613..964c2fb89 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -425,10 +425,6 @@ bool ArmMir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div if (pattern == DivideNone) { return false; } - // Tuning: add rem patterns - if (!is_div) { - return false; - } RegStorage r_magic = AllocTemp(); LoadConstant(r_magic, magic_table[lit].magic); @@ -439,23 +435,136 @@ bool ArmMir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div NewLIR4(kThumb2Smull, r_lo.GetReg(), r_hi.GetReg(), r_magic.GetReg(), rl_src.reg.GetReg()); switch (pattern) { case Divide3: - OpRegRegRegShift(kOpSub, rl_result.reg.GetReg(), r_hi.GetReg(), - rl_src.reg.GetReg(), EncodeShift(kArmAsr, 31)); + OpRegRegRegShift(kOpSub, rl_result.reg, r_hi, rl_src.reg, EncodeShift(kArmAsr, 31)); break; case Divide5: OpRegRegImm(kOpAsr, r_lo, rl_src.reg, 31); - OpRegRegRegShift(kOpRsub, rl_result.reg.GetReg(), r_lo.GetReg(), r_hi.GetReg(), - EncodeShift(kArmAsr, magic_table[lit].shift)); + OpRegRegRegShift(kOpRsub, rl_result.reg, r_lo, r_hi, + EncodeShift(kArmAsr, magic_table[lit].shift)); break; case Divide7: OpRegReg(kOpAdd, r_hi, rl_src.reg); OpRegRegImm(kOpAsr, r_lo, rl_src.reg, 31); - OpRegRegRegShift(kOpRsub, rl_result.reg.GetReg(), r_lo.GetReg(), r_hi.GetReg(), - EncodeShift(kArmAsr, magic_table[lit].shift)); + OpRegRegRegShift(kOpRsub, rl_result.reg, r_lo, r_hi, + EncodeShift(kArmAsr, magic_table[lit].shift)); break; default: LOG(FATAL) << "Unexpected pattern: " << pattern; } + + if (!is_div) { + RegStorage tmp1 = r_lo; + EasyMultiplyOp ops[2]; + + bool canEasyMultiply = GetEasyMultiplyTwoOps(lit, ops); + DCHECK_NE(canEasyMultiply, false); + + GenEasyMultiplyTwoOps(tmp1, rl_result.reg, ops); + OpRegRegReg(kOpSub, rl_result.reg, rl_src.reg, tmp1); + } + + StoreValue(rl_dest, rl_result); + return true; +} + +// Try to convert *lit to 1 RegRegRegShift/RegRegShift form. +bool ArmMir2Lir::GetEasyMultiplyOp(int lit, ArmMir2Lir::EasyMultiplyOp* op) { + if (IsPowerOfTwo(lit)) { + op->op = kOpLsl; + op->shift = LowestSetBit(lit); + return true; + } + + if (IsPowerOfTwo(lit - 1)) { + op->op = kOpAdd; + op->shift = LowestSetBit(lit - 1); + return true; + } + + if (IsPowerOfTwo(lit + 1)) { + op->op = kOpRsub; + op->shift = LowestSetBit(lit + 1); + return true; + } + + op->op = kOpInvalid; + return false; +} + +// Try to convert *lit to 1~2 RegRegRegShift/RegRegShift forms. +bool ArmMir2Lir::GetEasyMultiplyTwoOps(int lit, EasyMultiplyOp* ops) { + GetEasyMultiplyOp(lit, &ops[0]); + if (GetEasyMultiplyOp(lit, &ops[0])) { + ops[1].op = kOpInvalid; + return true; + } + + int lit1 = lit; + uint32_t shift = LowestSetBit(lit1); + if (GetEasyMultiplyOp(lit1 >> shift, &ops[0])) { + ops[1].op = kOpLsl; + ops[1].shift = shift; + return true; + } + + lit1 = lit - 1; + shift = LowestSetBit(lit1); + if (GetEasyMultiplyOp(lit1 >> shift, &ops[0])) { + ops[1].op = kOpAdd; + ops[1].shift = shift; + return true; + } + + lit1 = lit + 1; + shift = LowestSetBit(lit1); + if (GetEasyMultiplyOp(lit1 >> shift, &ops[0])) { + ops[1].op = kOpRsub; + ops[1].shift = shift; + return true; + } + + return false; +} + +void ArmMir2Lir::GenEasyMultiplyTwoOps(RegStorage r_dest, RegStorage r_src, EasyMultiplyOp* ops) { + // dest = ( src << shift1) + [ src | -src | 0 ] + // dest = (dest << shift2) + [ src | -src | 0 ] + for (int i = 0; i < 2; i++) { + RegStorage r_src2; + if (i == 0) { + r_src2 = r_src; + } else { + r_src2 = r_dest; + } + switch (ops[i].op) { + case kOpLsl: + OpRegRegImm(kOpLsl, r_dest, r_src2, ops[i].shift); + break; + case kOpAdd: + OpRegRegRegShift(kOpAdd, r_dest, r_src, r_src2, EncodeShift(kArmLsl, ops[i].shift)); + break; + case kOpRsub: + OpRegRegRegShift(kOpRsub, r_dest, r_src, r_src2, EncodeShift(kArmLsl, ops[i].shift)); + break; + default: + DCHECK_NE(i, 0); + DCHECK_EQ(ops[i].op, kOpInvalid); + break; + } + } +} + +bool ArmMir2Lir::EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) { + EasyMultiplyOp ops[2]; + + if (!GetEasyMultiplyTwoOps(lit, ops)) { + return false; + } + + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + + GenEasyMultiplyTwoOps(rl_result.reg, rl_src.reg, ops); StoreValue(rl_dest, rl_result); return true; } @@ -752,7 +861,7 @@ LIR* ArmMir2Lir::OpVstm(RegStorage r_base, int count) { void ArmMir2Lir::GenMultiplyByTwoBitMultiplier(RegLocation rl_src, RegLocation rl_result, int lit, int first_bit, int second_bit) { - OpRegRegRegShift(kOpAdd, rl_result.reg.GetReg(), rl_src.reg.GetReg(), rl_src.reg.GetReg(), + OpRegRegRegShift(kOpAdd, rl_result.reg, rl_src.reg, rl_src.reg, EncodeShift(kArmLsl, second_bit - first_bit)); if (first_bit != 0) { OpRegRegImm(kOpLsl, rl_result.reg, rl_result.reg, first_bit); @@ -898,8 +1007,7 @@ void ArmMir2Lir::GenMulLong(Instruction::Code opcode, RegLocation rl_dest, NewLIR3(kThumb2MulRRR, tmp1.GetReg(), rl_src1.reg.GetLowReg(), rl_src1.reg.GetHighReg()); NewLIR4(kThumb2Umull, res_lo.GetReg(), res_hi.GetReg(), rl_src1.reg.GetLowReg(), rl_src1.reg.GetLowReg()); - OpRegRegRegShift(kOpAdd, res_hi.GetReg(), res_hi.GetReg(), tmp1.GetReg(), - EncodeShift(kArmLsl, 1)); + OpRegRegRegShift(kOpAdd, res_hi, res_hi, tmp1, EncodeShift(kArmLsl, 1)); } else { NewLIR3(kThumb2MulRRR, tmp1.GetReg(), rl_src2.reg.GetLowReg(), rl_src1.reg.GetHighReg()); if (reg_status == 2) { @@ -1009,8 +1117,7 @@ void ArmMir2Lir::GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, } else { // No special indexed operation, lea + load w/ displacement reg_ptr = AllocTemp(); - OpRegRegRegShift(kOpAdd, reg_ptr.GetReg(), rl_array.reg.GetReg(), rl_index.reg.GetReg(), - EncodeShift(kArmLsl, scale)); + OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.reg, rl_index.reg, EncodeShift(kArmLsl, scale)); FreeTemp(rl_index.reg.GetReg()); } rl_result = EvalLoc(rl_dest, reg_class, true); @@ -1117,8 +1224,7 @@ void ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, rl_src = LoadValue(rl_src, reg_class); } if (!constant_index) { - OpRegRegRegShift(kOpAdd, reg_ptr.GetReg(), rl_array.reg.GetReg(), rl_index.reg.GetReg(), - EncodeShift(kArmLsl, scale)); + OpRegRegRegShift(kOpAdd, reg_ptr, rl_array.reg, rl_index.reg, EncodeShift(kArmLsl, scale)); } if (needs_range_check) { if (constant_index) { @@ -1183,7 +1289,7 @@ void ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, LoadConstant(rl_result.reg.GetLow(), 0); } else { OpRegRegImm(kOpLsl, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), shift_amount); - OpRegRegRegShift(kOpOr, rl_result.reg.GetHighReg(), rl_result.reg.GetHighReg(), rl_src.reg.GetLowReg(), + OpRegRegRegShift(kOpOr, rl_result.reg.GetHigh(), rl_result.reg.GetHigh(), rl_src.reg.GetLow(), EncodeShift(kArmLsr, 32 - shift_amount)); OpRegRegImm(kOpLsl, rl_result.reg.GetLow(), rl_src.reg.GetLow(), shift_amount); } @@ -1199,7 +1305,7 @@ void ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, } else { RegStorage t_reg = AllocTemp(); OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetLow(), shift_amount); - OpRegRegRegShift(kOpOr, rl_result.reg.GetLowReg(), t_reg.GetReg(), rl_src.reg.GetHighReg(), + OpRegRegRegShift(kOpOr, rl_result.reg.GetLow(), t_reg, rl_src.reg.GetHigh(), EncodeShift(kArmLsl, 32 - shift_amount)); FreeTemp(t_reg); OpRegRegImm(kOpAsr, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), shift_amount); @@ -1216,7 +1322,7 @@ void ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, } else { RegStorage t_reg = AllocTemp(); OpRegRegImm(kOpLsr, t_reg, rl_src.reg.GetLow(), shift_amount); - OpRegRegRegShift(kOpOr, rl_result.reg.GetLowReg(), t_reg.GetReg(), rl_src.reg.GetHighReg(), + OpRegRegRegShift(kOpOr, rl_result.reg.GetLow(), t_reg, rl_src.reg.GetHigh(), EncodeShift(kArmLsl, 32 - shift_amount)); FreeTemp(t_reg); OpRegRegImm(kOpLsr, rl_result.reg.GetHigh(), rl_src.reg.GetHigh(), shift_amount); diff --git a/compiler/dex/quick/arm/utility_arm.cc b/compiler/dex/quick/arm/utility_arm.cc index 1ec0a2c65..cf90fb1b5 100644 --- a/compiler/dex/quick/arm/utility_arm.cc +++ b/compiler/dex/quick/arm/utility_arm.cc @@ -234,9 +234,10 @@ LIR* ArmMir2Lir::OpReg(OpKind op, RegStorage r_dest_src) { return NewLIR1(opcode, r_dest_src.GetReg()); } -LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, +LIR* ArmMir2Lir::OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, int shift) { - bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2)); + bool thumb_form = + ((shift == 0) && ARM_LOWREG(r_dest_src1.GetReg()) && ARM_LOWREG(r_src2.GetReg())); ArmOpcode opcode = kThumbBkpt; switch (op) { case kOpAdc: @@ -255,9 +256,9 @@ LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, case kOpCmp: if (thumb_form) opcode = kThumbCmpRR; - else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2)) + else if ((shift == 0) && !ARM_LOWREG(r_dest_src1.GetReg()) && !ARM_LOWREG(r_src2.GetReg())) opcode = kThumbCmpHH; - else if ((shift == 0) && ARM_LOWREG(r_dest_src1)) + else if ((shift == 0) && ARM_LOWREG(r_dest_src1.GetReg())) opcode = kThumbCmpLH; else if (shift == 0) opcode = kThumbCmpHL; @@ -269,11 +270,11 @@ LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, break; case kOpMov: DCHECK_EQ(shift, 0); - if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2)) + if (ARM_LOWREG(r_dest_src1.GetReg()) && ARM_LOWREG(r_src2.GetReg())) opcode = kThumbMovRR; - else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2)) + else if (!ARM_LOWREG(r_dest_src1.GetReg()) && !ARM_LOWREG(r_src2.GetReg())) opcode = kThumbMovRR_H2H; - else if (ARM_LOWREG(r_dest_src1)) + else if (ARM_LOWREG(r_dest_src1.GetReg())) opcode = kThumbMovRR_H2L; else opcode = kThumbMovRR_L2H; @@ -324,7 +325,7 @@ LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, DCHECK_EQ(shift, 0); if (!thumb_form) { // Binary, but rm is encoded twice. - return NewLIR3(kThumb2RevRR, r_dest_src1, r_src2, r_src2); + return NewLIR3(kThumb2RevRR, r_dest_src1.GetReg(), r_src2.GetReg(), r_src2.GetReg()); } opcode = kThumbRev; break; @@ -332,34 +333,34 @@ LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, DCHECK_EQ(shift, 0); if (!thumb_form) { // Binary, but rm is encoded twice. - return NewLIR3(kThumb2RevshRR, r_dest_src1, r_src2, r_src2); + return NewLIR3(kThumb2RevshRR, r_dest_src1.GetReg(), r_src2.GetReg(), r_src2.GetReg()); } opcode = kThumbRevsh; break; case kOp2Byte: DCHECK_EQ(shift, 0); - return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 8); + return NewLIR4(kThumb2Sbfx, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 8); case kOp2Short: DCHECK_EQ(shift, 0); - return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 16); + return NewLIR4(kThumb2Sbfx, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 16); case kOp2Char: DCHECK_EQ(shift, 0); - return NewLIR4(kThumb2Ubfx, r_dest_src1, r_src2, 0, 16); + return NewLIR4(kThumb2Ubfx, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 16); default: LOG(FATAL) << "Bad opcode: " << op; break; } DCHECK(!IsPseudoLirOp(opcode)); if (EncodingMap[opcode].flags & IS_BINARY_OP) { - return NewLIR2(opcode, r_dest_src1, r_src2); + return NewLIR2(opcode, r_dest_src1.GetReg(), r_src2.GetReg()); } else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) { if (EncodingMap[opcode].field_loc[2].kind == kFmtShift) { - return NewLIR3(opcode, r_dest_src1, r_src2, shift); + return NewLIR3(opcode, r_dest_src1.GetReg(), r_src2.GetReg(), shift); } else { - return NewLIR3(opcode, r_dest_src1, r_dest_src1, r_src2); + return NewLIR3(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_src2.GetReg()); } } else if (EncodingMap[opcode].flags & IS_QUAD_OP) { - return NewLIR4(opcode, r_dest_src1, r_dest_src1, r_src2, shift); + return NewLIR4(opcode, r_dest_src1.GetReg(), r_dest_src1.GetReg(), r_src2.GetReg(), shift); } else { LOG(FATAL) << "Unexpected encoding operand count"; return NULL; @@ -367,7 +368,7 @@ LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2, } LIR* ArmMir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) { - return OpRegRegShift(op, r_dest_src1.GetReg(), r_src2.GetReg(), 0); + return OpRegRegShift(op, r_dest_src1, r_src2, 0); } LIR* ArmMir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, MoveType move_type) { @@ -385,11 +386,11 @@ LIR* ArmMir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, Re return NULL; } -LIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, int r_dest, int r_src1, - int r_src2, int shift) { +LIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1, + RegStorage r_src2, int shift) { ArmOpcode opcode = kThumbBkpt; - bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) && - ARM_LOWREG(r_src2); + bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest.GetReg()) && ARM_LOWREG(r_src1.GetReg()) && + ARM_LOWREG(r_src2.GetReg()); switch (op) { case kOpAdd: opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR; @@ -448,15 +449,15 @@ LIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, int r_dest, int r_src1, } DCHECK(!IsPseudoLirOp(opcode)); if (EncodingMap[opcode].flags & IS_QUAD_OP) { - return NewLIR4(opcode, r_dest, r_src1, r_src2, shift); + return NewLIR4(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), shift); } else { DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP); - return NewLIR3(opcode, r_dest, r_src1, r_src2); + return NewLIR3(opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg()); } } LIR* ArmMir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) { - return OpRegRegRegShift(op, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), 0); + return OpRegRegRegShift(op, r_dest, r_src1, r_src2, 0); } LIR* ArmMir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) { diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 2afa5ca81..b23e10f28 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -1626,14 +1626,31 @@ bool Mir2Lir::HandleEasyDivRem(Instruction::Code dalvik_opcode, bool is_div, // Returns true if it added instructions to 'cu' to multiply 'rl_src' by 'lit' // and store the result in 'rl_dest'. bool Mir2Lir::HandleEasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) { + if (lit < 0) { + return false; + } + if (lit == 0) { + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + LoadConstant(rl_result.reg, 0); + StoreValue(rl_dest, rl_result); + return true; + } + if (lit == 1) { + rl_src = LoadValue(rl_src, kCoreReg); + RegLocation rl_result = EvalLoc(rl_dest, kCoreReg, true); + OpRegCopy(rl_result.reg, rl_src.reg); + StoreValue(rl_dest, rl_result); + return true; + } + // There is RegRegRegShift on Arm, so check for more special cases + if (cu_->instruction_set == kThumb2) { + return EasyMultiply(rl_src, rl_dest, lit); + } // Can we simplify this multiplication? bool power_of_two = false; bool pop_count_le2 = false; bool power_of_two_minus_one = false; - if (lit < 2) { - // Avoid special cases. - return false; - } else if (IsPowerOfTwo(lit)) { + if (IsPowerOfTwo(lit)) { power_of_two = true; } else if (IsPopCountLE2(lit)) { pop_count_le2 = true; diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h index bc1ad02ce..0ef43b319 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -22,13 +22,14 @@ namespace art { -class MipsMir2Lir : public Mir2Lir { +class MipsMir2Lir FINAL : public Mir2Lir { public: MipsMir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); // Required for target - codegen utilities. bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, RegLocation rl_dest, int lit); + bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; LIR* CheckSuspendUsingLoad() OVERRIDE; RegStorage LoadHelper(ThreadOffset offset); LIR* LoadBaseDisp(int r_base, int displacement, int r_dest, OpSize size, int s_reg); diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index dfe8b3527..270d89519 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -368,6 +368,11 @@ bool MipsMir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_di return false; } +bool MipsMir2Lir::EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) { + LOG(FATAL) << "Unexpected use of easyMultiply in Mips"; + return false; +} + LIR* MipsMir2Lir::OpIT(ConditionCode cond, const char* guide) { LOG(FATAL) << "Unexpected use of OpIT in Mips"; return NULL; diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 1c8f6dc40..68c3d0fda 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -811,6 +811,7 @@ class Mir2Lir : public Backend { // Required for target - codegen helpers. virtual bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, RegLocation rl_dest, int lit) = 0; + virtual bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) = 0; virtual LIR* CheckSuspendUsingLoad() = 0; virtual RegStorage LoadHelper(ThreadOffset offset) = 0; virtual LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size, diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 6d427e7bc..4c495a16c 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -22,13 +22,14 @@ namespace art { -class X86Mir2Lir : public Mir2Lir { +class X86Mir2Lir FINAL : public Mir2Lir { public: X86Mir2Lir(CompilationUnit* cu, MIRGraph* mir_graph, ArenaAllocator* arena); // Required for target - codegen helpers. bool SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, RegLocation rl_dest, int lit); + bool EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) OVERRIDE; LIR* CheckSuspendUsingLoad() OVERRIDE; RegStorage LoadHelper(ThreadOffset offset); LIR* LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, OpSize size, diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 37b2b37b4..5ef706073 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -909,6 +909,11 @@ bool X86Mir2Lir::SmallLiteralDivRem(Instruction::Code dalvik_opcode, bool is_div return false; } +bool X86Mir2Lir::EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) { + LOG(FATAL) << "Unexpected use of easyMultiply in x86"; + return false; +} + LIR* X86Mir2Lir::OpIT(ConditionCode cond, const char* guide) { LOG(FATAL) << "Unexpected use of OpIT in x86"; return NULL; -- 2.11.0