Revert "Revert "Optimize easy multiply and easy div remainder.""
This reverts commit 3654a6f50a948ead89627f398aaf86a2c2db0088.
Remove the part of the change that confused !is_div with being multiply rather
than implying remainder.
Change-Id: I202610069c69351259a320e8852543cbed4c3b3e
diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h
index 0f1e171..6df341b 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 @@
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 @@
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 46db466..1656aa2 100644
--- a/compiler/dex/quick/arm/int_arm.cc
+++ b/compiler/dex/quick/arm/int_arm.cc
@@ -439,19 +439,18 @@
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;
@@ -460,6 +459,108 @@
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;
+}
+
LIR* ArmMir2Lir::GenRegMemCheck(ConditionCode c_code, RegStorage reg1, RegStorage base,
int offset, ThrowKind kind) {
LOG(FATAL) << "Unexpected use of GenRegMemCheck for Arm";
@@ -752,7 +853,7 @@
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 +999,7 @@
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 +1109,7 @@
} 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 +1216,7 @@
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 +1281,7 @@
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 +1297,7 @@
} 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 +1314,7 @@
} 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 1ec0a2c..cf90fb1 100644
--- a/compiler/dex/quick/arm/utility_arm.cc
+++ b/compiler/dex/quick/arm/utility_arm.cc
@@ -234,9 +234,10 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
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 @@
}
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 2afa5ca..8f283d3 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -1626,14 +1626,32 @@
// 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.
+ // TODO: disabled, need to handle case of "dest == src" properly.
+ if (false && 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 bc1ad02..0ef43b3 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 dfe8b35..270d895 100644
--- a/compiler/dex/quick/mips/int_mips.cc
+++ b/compiler/dex/quick/mips/int_mips.cc
@@ -368,6 +368,11 @@
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 bac35aa..946adc5 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -811,6 +811,7 @@
// 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 6d427e7..4c495a1 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 851f448..3b73082 100644
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -909,6 +909,11 @@
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;