diff options
author | Razvan A Lupusoru <razvan.a.lupusoru@intel.com> | 2014-09-29 16:42:11 -0700 |
---|---|---|
committer | Razvan A Lupusoru <razvan.a.lupusoru@intel.com> | 2014-10-14 13:06:52 -0700 |
commit | 5c5676b26a08454b3f0133783778991bbe5dd681 (patch) | |
tree | 233f278fb590036beaf327e0a345f177b070df43 /compiler | |
parent | e4228d93de256c72df9d57f0def938b11cfe21a1 (diff) | |
download | art-5c5676b26a08454b3f0133783778991bbe5dd681.zip art-5c5676b26a08454b3f0133783778991bbe5dd681.tar.gz art-5c5676b26a08454b3f0133783778991bbe5dd681.tar.bz2 |
ART: Add div/rem zero check elimination flag
Just as with other throwing bytecodes, it is possible to prove in some cases
that a divide/remainder won't throw ArithmeticException. For example, in case
two divides with same denominator are in order, then provably the second one
cannot throw if the first one did not.
This patch adds the elimination flag and updates the signature of several
Mir2Lir methods to take the instruction optimization flags into account.
Change-Id: I0b078cf7f29899f0f059db1f14b65a37444b84e8
Signed-off-by: Razvan A Lupusoru <razvan.a.lupusoru@intel.com>
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/dex/compiler_enums.h | 1 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 1 | ||||
-rw-r--r-- | compiler/dex/quick/arm/codegen_arm.h | 10 | ||||
-rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 18 | ||||
-rw-r--r-- | compiler/dex/quick/arm64/codegen_arm64.h | 12 | ||||
-rw-r--r-- | compiler/dex/quick/arm64/int_arm64.cc | 21 | ||||
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 14 | ||||
-rw-r--r-- | compiler/dex/quick/mips/codegen_mips.h | 10 | ||||
-rw-r--r-- | compiler/dex/quick/mips/int_mips.cc | 13 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.cc | 14 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 13 | ||||
-rw-r--r-- | compiler/dex/quick/x86/codegen_x86.h | 23 | ||||
-rwxr-xr-x | compiler/dex/quick/x86/int_x86.cc | 49 | ||||
-rwxr-xr-x | compiler/dex/quick/x86/target_x86.cc | 2 |
14 files changed, 109 insertions, 92 deletions
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h index e4003bf..763c34b 100644 --- a/compiler/dex/compiler_enums.h +++ b/compiler/dex/compiler_enums.h @@ -306,6 +306,7 @@ enum MIROptimizationFlagPositions { kMIRIgnoreRangeCheck, kMIRRangeCheckOnly, kMIRIgnoreClInitCheck, + kMirIgnoreDivZeroCheck, kMIRInlined, // Invoke is inlined (ie dead). kMIRInlinedPred, // Invoke is inlined via prediction. kMIRCallee, // Instruction is inlined from callee. diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index cc215bd..87a2b34 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -155,6 +155,7 @@ enum OatMethodAttributes { #define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck) #define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly) #define MIR_IGNORE_CLINIT_CHECK (1 << kMIRIgnoreClInitCheck) +#define MIR_IGNORE_DIV_ZERO_CHECK (1 << kMirIgnoreDivZeroCheck) #define MIR_INLINED (1 << kMIRInlined) #define MIR_INLINED_PRED (1 << kMIRInlinedPred) #define MIR_CALLEE (1 << kMIRCallee) diff --git a/compiler/dex/quick/arm/codegen_arm.h b/compiler/dex/quick/arm/codegen_arm.h index 1c87a03..6fd29f2 100644 --- a/compiler/dex/quick/arm/codegen_arm.h +++ b/compiler/dex/quick/arm/codegen_arm.h @@ -87,15 +87,15 @@ class ArmMir2Lir FINAL : public Mir2Lir { // Required for target - Dalvik-level generators. void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) OVERRIDE; + RegLocation rl_src2, int flags) OVERRIDE; void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); + RegLocation rl_src1, RegLocation rl_src2, int flags); void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale); void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark); void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_shift); + RegLocation rl_src1, RegLocation rl_shift, int flags); void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, @@ -224,8 +224,8 @@ class ArmMir2Lir FINAL : public Mir2Lir { void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); void AssignDataOffsets(); 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); + bool is_div, int flags) OVERRIDE; + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE; typedef struct { OpKind op; uint32_t shift; diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index 018dc1c..9742243 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -678,7 +678,7 @@ bool ArmMir2Lir::EasyMultiply(RegLocation rl_src, RegLocation rl_dest, int lit) } RegLocation ArmMir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div, bool check_zero) { + RegLocation rl_src2, bool is_div, int flags) { LOG(FATAL) << "Unexpected use of GenDivRem for Arm"; return rl_dest; } @@ -1264,7 +1264,7 @@ void ArmMir2Lir::GenMulLong(Instruction::Code opcode, RegLocation rl_dest, } void ArmMir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) { + RegLocation rl_src2, int flags) { switch (opcode) { case Instruction::MUL_LONG: case Instruction::MUL_LONG_2ADDR: @@ -1279,7 +1279,7 @@ void ArmMir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, R } // Fallback for all other ops. - Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); } /* @@ -1464,7 +1464,8 @@ void ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, void ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) { + RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift, + int flags) { rl_src = LoadValueWide(rl_src, kCoreReg); // Per spec, we only care about low 6 bits of shift amount. int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f; @@ -1537,11 +1538,12 @@ void ArmMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, } void ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, + int flags) { if ((opcode == Instruction::SUB_LONG_2ADDR) || (opcode == Instruction::SUB_LONG)) { if (!rl_src2.is_const) { // Don't bother with special handling for subtract from immediate. - GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); return; } } else { @@ -1552,7 +1554,7 @@ void ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode, } } if (PartiallyIntersects(rl_src1, rl_dest)) { - GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); return; } DCHECK(rl_src2.is_const); @@ -1569,7 +1571,7 @@ void ArmMir2Lir::GenArithImmOpLong(Instruction::Code opcode, case Instruction::SUB_LONG: case Instruction::SUB_LONG_2ADDR: if ((mod_imm_lo < 0) || (mod_imm_hi < 0)) { - GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); return; } break; diff --git a/compiler/dex/quick/arm64/codegen_arm64.h b/compiler/dex/quick/arm64/codegen_arm64.h index 510bd4c..9f02606 100644 --- a/compiler/dex/quick/arm64/codegen_arm64.h +++ b/compiler/dex/quick/arm64/codegen_arm64.h @@ -141,13 +141,13 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation lr_shift) OVERRIDE; void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) OVERRIDE; + RegLocation rl_src2, int flags) OVERRIDE; void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale) OVERRIDE; void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark) OVERRIDE; void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_shift) OVERRIDE; + RegLocation rl_shift, int flags) OVERRIDE; void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) OVERRIDE; void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, @@ -173,7 +173,7 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { bool GenInlinedArrayCopyCharArray(CallInfo* info) OVERRIDE; void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) OVERRIDE; + RegLocation rl_src2, int flags) OVERRIDE; RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div) OVERRIDE; RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div) @@ -363,8 +363,8 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { void InsertFixupBefore(LIR* prev_lir, LIR* orig_lir, LIR* new_lir); void AssignDataOffsets(); 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); + bool is_div, int flags) OVERRIDE; + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE; size_t GetLoadStoreSize(LIR* lir); bool SmallLiteralDivRem64(Instruction::Code dalvik_opcode, bool is_div, RegLocation rl_src, @@ -413,7 +413,7 @@ class Arm64Mir2Lir FINAL : public Mir2Lir { void GenNotLong(RegLocation rl_dest, RegLocation rl_src); void GenNegLong(RegLocation rl_dest, RegLocation rl_src); void GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div); + RegLocation rl_src2, bool is_div, int flags); InToRegStorageMapping in_to_reg_storage_mapping_; static const A64EncodingMap EncodingMap[kA64Last]; diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc index abcb30f..6e7241d 100644 --- a/compiler/dex/quick/arm64/int_arm64.cc +++ b/compiler/dex/quick/arm64/int_arm64.cc @@ -614,7 +614,7 @@ RegLocation Arm64Mir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int } RegLocation Arm64Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div, bool check_zero) { + RegLocation rl_src2, bool is_div, int flags) { LOG(FATAL) << "Unexpected use of GenDivRem for Arm64"; return rl_dest; } @@ -1020,7 +1020,7 @@ void Arm64Mir2Lir::GenIntToLong(RegLocation rl_dest, RegLocation rl_src) { } void Arm64Mir2Lir::GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2, bool is_div) { + RegLocation rl_src1, RegLocation rl_src2, bool is_div, int flags) { if (rl_src2.is_const) { DCHECK(rl_src2.wide); int64_t lit = mir_graph_->ConstantValueWide(rl_src2); @@ -1032,7 +1032,9 @@ void Arm64Mir2Lir::GenDivRemLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_result; rl_src1 = LoadValueWide(rl_src1, kCoreReg); rl_src2 = LoadValueWide(rl_src2, kCoreReg); - GenDivZeroCheck(rl_src2.reg); + if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { + GenDivZeroCheck(rl_src2.reg); + } rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, is_div); StoreValueWide(rl_dest, rl_result); } @@ -1067,7 +1069,7 @@ void Arm64Mir2Lir::GenNotLong(RegLocation rl_dest, RegLocation rl_src) { } void Arm64Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_src1, RegLocation rl_src2, int flags) { switch (opcode) { case Instruction::NOT_LONG: GenNotLong(rl_dest, rl_src2); @@ -1086,11 +1088,11 @@ void Arm64Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, return; case Instruction::DIV_LONG: case Instruction::DIV_LONG_2ADDR: - GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true); + GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true, flags); return; case Instruction::REM_LONG: case Instruction::REM_LONG_2ADDR: - GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false); + GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false, flags); return; case Instruction::AND_LONG_2ADDR: case Instruction::AND_LONG: @@ -1312,7 +1314,8 @@ void Arm64Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, } void Arm64Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift) { + RegLocation rl_dest, RegLocation rl_src, RegLocation rl_shift, + int flags) { OpKind op = kOpBkpt; // Per spec, we only care about low 6 bits of shift amount. int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f; @@ -1344,7 +1347,7 @@ void Arm64Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, } void Arm64Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_src1, RegLocation rl_src2, int flags) { OpKind op = kOpBkpt; switch (opcode) { case Instruction::ADD_LONG: @@ -1373,7 +1376,7 @@ void Arm64Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_de if (op == kOpSub) { if (!rl_src2.is_const) { - return GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + return GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); } } else { // Associativity. diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 12ca065..268f445 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -1501,7 +1501,7 @@ void Mir2Lir::GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_src1, RegLocation rl_src2, int flags) { DCHECK(cu_->instruction_set != kX86 && cu_->instruction_set != kX86_64); OpKind op = kOpBkpt; bool is_div_rem = false; @@ -1600,7 +1600,7 @@ void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, if (cu_->instruction_set == kMips || cu_->instruction_set == kArm64) { rl_src1 = LoadValue(rl_src1, kCoreReg); rl_src2 = LoadValue(rl_src2, kCoreReg); - if (check_zero) { + if (check_zero && (flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { GenDivZeroCheck(rl_src2.reg); } rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv); @@ -1611,7 +1611,7 @@ void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, // calculate using a MUL and subtract. rl_src1 = LoadValue(rl_src1, kCoreReg); rl_src2 = LoadValue(rl_src2, kCoreReg); - if (check_zero) { + if (check_zero && (flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { GenDivZeroCheck(rl_src2.reg); } rl_result = GenDivRem(rl_dest, rl_src1.reg, rl_src2.reg, op == kOpDiv); @@ -1625,7 +1625,7 @@ void Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, LoadValueDirectFixed(rl_src2, TargetReg(kArg1, kNotWide)); RegStorage r_tgt = CallHelperSetup(kQuickIdivmod); LoadValueDirectFixed(rl_src1, TargetReg(kArg0, kNotWide)); - if (check_zero) { + if (check_zero && (flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { GenDivZeroCheck(TargetReg(kArg1, kNotWide)); } // NOTE: callout here is not a safepoint. @@ -1912,7 +1912,7 @@ void Mir2Lir::GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, Re } void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_src1, RegLocation rl_src2, int flags) { RegLocation rl_result; OpKind first_op = kOpBkpt; OpKind second_op = kOpBkpt; @@ -1997,7 +1997,9 @@ void Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegStorage r_tmp2 = TargetReg(kArg2, kWide); LoadValueDirectWideFixed(rl_src2, r_tmp2); RegStorage r_tgt = CallHelperSetup(target); - GenDivZeroCheckWide(r_tmp2); + if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { + GenDivZeroCheckWide(r_tmp2); + } LoadValueDirectWideFixed(rl_src1, r_tmp1); // NOTE: callout here is not a safepoint CallHelper(r_tgt, target, false /* not safepoint */); diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h index bd709f3..508d474 100644 --- a/compiler/dex/quick/mips/codegen_mips.h +++ b/compiler/dex/quick/mips/codegen_mips.h @@ -86,13 +86,13 @@ class MipsMir2Lir FINAL : public Mir2Lir { // Required for target - Dalvik-level generators. void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); + RegLocation rl_src1, RegLocation rl_src2, int flags); void GenArrayGet(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_dest, int scale); void GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark); void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_shift); + RegLocation rl_shift, int flags); void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); void GenArithOpFloat(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, @@ -108,7 +108,7 @@ class MipsMir2Lir FINAL : public Mir2Lir { bool GenInlinedPeek(CallInfo* info, OpSize size); bool GenInlinedPoke(CallInfo* info, OpSize size); void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) OVERRIDE; + RegLocation rl_src2, int flags) OVERRIDE; RegLocation GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegStorage reg_hi, bool is_div); RegLocation GenDivRemLit(RegLocation rl_dest, RegStorage reg_lo, int lit, bool is_div); void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2); @@ -190,8 +190,8 @@ class MipsMir2Lir FINAL : public Mir2Lir { void ConvertShortToLongBranch(LIR* lir); 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); + RegLocation rl_src2, bool is_div, int flags) OVERRIDE; + RegLocation GenDivRemLit(RegLocation rl_dest, RegLocation rl_src1, int lit, bool is_div) OVERRIDE; }; } // namespace art diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index 30aa611..baf7311 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -263,7 +263,7 @@ RegLocation MipsMir2Lir::GenDivRemLit(RegLocation rl_dest, RegStorage reg1, int } RegLocation MipsMir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div, bool check_zero) { + RegLocation rl_src2, bool is_div, int flags) { LOG(FATAL) << "Unexpected use of GenDivRem for Mips"; return rl_dest; } @@ -437,7 +437,7 @@ void MipsMir2Lir::GenSubLong(Instruction::Code opcode, RegLocation rl_dest, } void MipsMir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) { + RegLocation rl_src2, int flags) { switch (opcode) { case Instruction::ADD_LONG: case Instruction::ADD_LONG_2ADDR: @@ -456,7 +456,7 @@ void MipsMir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, } // Fallback for all other ops. - Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); } void MipsMir2Lir::GenNegLong(RegLocation rl_dest, RegLocation rl_src) { @@ -628,15 +628,16 @@ void MipsMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, } void MipsMir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_shift) { + RegLocation rl_src1, RegLocation rl_shift, int flags) { // Default implementation is just to ignore the constant case. GenShiftOpLong(opcode, rl_dest, rl_src1, rl_shift); } void MipsMir2Lir::GenArithImmOpLong(Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, + int flags) { // Default - bail to non-const handler. - GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); } } // namespace art diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 4399981..408606d 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -928,12 +928,12 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::NEG_INT: case Instruction::NOT_INT: - GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0]); + GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags); break; case Instruction::NEG_LONG: case Instruction::NOT_LONG: - GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0]); + GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[0], opt_flags); break; case Instruction::NEG_FLOAT: @@ -993,7 +993,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1].orig_sreg)); } else { - GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); } break; @@ -1013,7 +1013,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src[1]), opcode)) { GenArithOpIntLit(opcode, rl_dest, rl_src[0], mir_graph_->ConstantValue(rl_src[1])); } else { - GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpInt(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); } break; @@ -1028,7 +1028,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::OR_LONG_2ADDR: case Instruction::XOR_LONG_2ADDR: if (rl_src[0].is_const || rl_src[1].is_const) { - GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); break; } FALLTHROUGH_INTENDED; @@ -1038,7 +1038,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::MUL_LONG_2ADDR: case Instruction::DIV_LONG_2ADDR: case Instruction::REM_LONG_2ADDR: - GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); + GenArithOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); break; case Instruction::SHL_LONG: @@ -1048,7 +1048,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::SHR_LONG_2ADDR: case Instruction::USHR_LONG_2ADDR: if (rl_src[1].is_const) { - GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); + GenShiftImmOpLong(opcode, rl_dest, rl_src[0], rl_src[1], opt_flags); } else { GenShiftOpLong(opcode, rl_dest, rl_src[0], rl_src[1]); } diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index ea93bbe..3e0844b 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -857,7 +857,7 @@ class Mir2Lir : public Backend { void GenArithOpIntLit(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src, int lit); virtual void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); + RegLocation rl_src1, RegLocation rl_src2, int flags); void GenConversionCall(QuickEntrypointEnum trampoline, RegLocation rl_dest, RegLocation rl_src); virtual void GenSuspendTest(int opt_flags); virtual void GenSuspendTestAndBranch(int opt_flags, LIR* target); @@ -865,7 +865,7 @@ class Mir2Lir : public Backend { // This will be overridden by x86 implementation. virtual void GenConstWide(RegLocation rl_dest, int64_t value); virtual void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2); + RegLocation rl_src1, RegLocation rl_src2, int flags); // Shared by all targets - implemented in gen_invoke.cc. LIR* CallHelper(RegStorage r_tgt, QuickEntrypointEnum trampoline, bool safepoint_pc, @@ -1259,7 +1259,7 @@ class Mir2Lir : public Backend { // Required for target - Dalvik-level generators. virtual void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_src2) = 0; + RegLocation rl_src1, RegLocation rl_src2, int flags) = 0; virtual void GenArithOpDouble(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) = 0; @@ -1297,10 +1297,11 @@ class Mir2Lir : public Backend { * @param rl_src1 Numerator Location. * @param rl_src2 Divisor Location. * @param is_div 'true' if this is a division, 'false' for a remainder. - * @param check_zero 'true' if an exception should be generated if the divisor is 0. + * @param flags The instruction optimization flags. It can include information + * if exception check can be elided. */ virtual RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div, bool check_zero) = 0; + RegLocation rl_src2, bool is_div, int flags) = 0; /* * @brief Generate an integer div or rem operation by a literal. * @param rl_dest Destination Location. @@ -1382,7 +1383,7 @@ class Mir2Lir : public Backend { RegLocation rl_index, RegLocation rl_src, int scale, bool card_mark) = 0; virtual void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_shift) = 0; + RegLocation rl_src1, RegLocation rl_shift, int flags) = 0; // Required for target - single operation generators. virtual LIR* OpUnconditionalBranch(LIR* target) = 0; diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index b3544da..7b5b831 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -180,11 +180,11 @@ class X86Mir2Lir : public Mir2Lir { // Long instructions. void GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) OVERRIDE; + RegLocation rl_src2, int flags) OVERRIDE; void GenArithImmOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) OVERRIDE; + RegLocation rl_src2, int flags) OVERRIDE; void GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src1, RegLocation rl_shift) OVERRIDE; + RegLocation rl_src1, RegLocation rl_shift, int flags) OVERRIDE; void GenCmpLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) OVERRIDE; void GenIntToLong(RegLocation rl_dest, RegLocation rl_src) OVERRIDE; void GenShiftOpLong(Instruction::Code opcode, RegLocation rl_dest, @@ -314,9 +314,10 @@ class X86Mir2Lir : public Mir2Lir { * @param rl_dest Destination for the result. * @param rl_lhs Left hand operand. * @param rl_rhs Right hand operand. + * @param flags The instruction optimization flags. */ void GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_lhs, - RegLocation rl_rhs) OVERRIDE; + RegLocation rl_rhs, int flags) OVERRIDE; /* * @brief Load the Method* of a dex method into the register. @@ -768,10 +769,11 @@ class X86Mir2Lir : public Mir2Lir { * @param rl_src1 Numerator Location. * @param rl_src2 Divisor Location. * @param is_div 'true' if this is a division, 'false' for a remainder. - * @param check_zero 'true' if an exception should be generated if the divisor is 0. + * @param flags The instruction optimization flags. It can include information + * if exception check can be elided. */ RegLocation GenDivRem(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, - bool is_div, bool check_zero); + bool is_div, int flags); /* * @brief Generate an integer div or rem operation by a literal. @@ -788,10 +790,11 @@ class X86Mir2Lir : public Mir2Lir { * @param rl_dest The destination. * @param rl_src The value to be shifted. * @param shift_amount How much to shift. + * @param flags The instruction optimization flags. * @returns the RegLocation of the result. */ RegLocation GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src, int shift_amount); + RegLocation rl_src, int shift_amount, int flags); /* * Generate an imul of a register by a constant or a better sequence. * @param dest Destination Register. @@ -858,13 +861,13 @@ class X86Mir2Lir : public Mir2Lir { // Try to do a long multiplication where rl_src2 is a constant. This simplified setup might fail, // in which case false will be returned. - bool GenMulLongConst(RegLocation rl_dest, RegLocation rl_src1, int64_t val); + bool GenMulLongConst(RegLocation rl_dest, RegLocation rl_src1, int64_t val, int flags); void GenMulLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2); + RegLocation rl_src2, int flags); void GenNotLong(RegLocation rl_dest, RegLocation rl_src); void GenNegLong(RegLocation rl_dest, RegLocation rl_src); void GenDivRemLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div); + RegLocation rl_src2, bool is_div, int flags); void SpillCoreRegs(); void UnSpillCoreRegs(); diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 07034cb..a531e28 100755 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -768,7 +768,7 @@ RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, RegStorage reg_lo, RegSto } RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div, bool check_zero) { + RegLocation rl_src2, bool is_div, int flags) { // We have to use fixed registers, so flush all the temps. // Prepare for explicit register usage. @@ -783,7 +783,7 @@ RegLocation X86Mir2Lir::GenDivRem(RegLocation rl_dest, RegLocation rl_src1, // Copy LHS sign bit into EDX. NewLIR0(kx86Cdq32Da); - if (check_zero) { + if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { // Handle division by zero case. GenDivZeroCheck(rs_r1); } @@ -1501,7 +1501,7 @@ void X86Mir2Lir::GenImulMemImm(RegStorage dest, int sreg, int displacement, int } void X86Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) { + RegLocation rl_src2, int flags) { if (!cu_->target64) { // Some x86 32b ops are fallback. switch (opcode) { @@ -1510,7 +1510,7 @@ void X86Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, R case Instruction::DIV_LONG_2ADDR: case Instruction::REM_LONG: case Instruction::REM_LONG_2ADDR: - Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + Mir2Lir::GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); return; default: @@ -1536,17 +1536,17 @@ void X86Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, R case Instruction::MUL_LONG: case Instruction::MUL_LONG_2ADDR: - GenMulLong(opcode, rl_dest, rl_src1, rl_src2); + GenMulLong(opcode, rl_dest, rl_src1, rl_src2, flags); return; case Instruction::DIV_LONG: case Instruction::DIV_LONG_2ADDR: - GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true); + GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ true, flags); return; case Instruction::REM_LONG: case Instruction::REM_LONG_2ADDR: - GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false); + GenDivRemLong(opcode, rl_dest, rl_src1, rl_src2, /*is_div*/ false, flags); return; case Instruction::AND_LONG_2ADDR: @@ -1574,7 +1574,7 @@ void X86Mir2Lir::GenArithOpLong(Instruction::Code opcode, RegLocation rl_dest, R } } -bool X86Mir2Lir::GenMulLongConst(RegLocation rl_dest, RegLocation rl_src1, int64_t val) { +bool X86Mir2Lir::GenMulLongConst(RegLocation rl_dest, RegLocation rl_src1, int64_t val, int flags) { // All memory accesses below reference dalvik regs. ScopedMemRefType mem_ref_type(this, ResourceMask::kDalvikReg); @@ -1592,14 +1592,14 @@ bool X86Mir2Lir::GenMulLongConst(RegLocation rl_dest, RegLocation rl_src1, int64 StoreValueWide(rl_dest, rl_src1); return true; } else if (val == 2) { - GenArithOpLong(Instruction::ADD_LONG, rl_dest, rl_src1, rl_src1); + GenArithOpLong(Instruction::ADD_LONG, rl_dest, rl_src1, rl_src1, flags); return true; } else if (IsPowerOfTwo(val)) { int shift_amount = LowestSetBit(val); if (!PartiallyIntersects(rl_src1, rl_dest)) { rl_src1 = LoadValueWide(rl_src1, kCoreReg); RegLocation rl_result = GenShiftImmOpLong(Instruction::SHL_LONG, rl_dest, rl_src1, - shift_amount); + shift_amount, flags); StoreValueWide(rl_dest, rl_result); return true; } @@ -1653,13 +1653,13 @@ bool X86Mir2Lir::GenMulLongConst(RegLocation rl_dest, RegLocation rl_src1, int64 } void X86Mir2Lir::GenMulLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2) { + RegLocation rl_src2, int flags) { if (rl_src1.is_const) { std::swap(rl_src1, rl_src2); } if (rl_src2.is_const) { - if (GenMulLongConst(rl_dest, rl_src1, mir_graph_->ConstantValueWide(rl_src2))) { + if (GenMulLongConst(rl_dest, rl_src1, mir_graph_->ConstantValueWide(rl_src2), flags)) { return; } } @@ -2159,7 +2159,7 @@ void X86Mir2Lir::GenDivRemLongLit(RegLocation rl_dest, RegLocation rl_src, } void X86Mir2Lir::GenDivRemLong(Instruction::Code, RegLocation rl_dest, RegLocation rl_src1, - RegLocation rl_src2, bool is_div) { + RegLocation rl_src2, bool is_div, int flags) { if (!cu_->target64) { LOG(FATAL) << "Unexpected use GenDivRemLong()"; return; @@ -2186,7 +2186,9 @@ void X86Mir2Lir::GenDivRemLong(Instruction::Code, RegLocation rl_dest, RegLocati NewLIR0(kx86Cqo64Da); // Handle division by zero case. - GenDivZeroCheckWide(rs_r1q); + if ((flags & MIR_IGNORE_DIV_ZERO_CHECK) == 0) { + GenDivZeroCheckWide(rs_r1q); + } // Have to catch 0x8000000000000000/-1 case, or we will get an exception! NewLIR2(kX86Cmp64RI8, rs_r1q.GetReg(), -1); @@ -2387,7 +2389,7 @@ void X86Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, } RegLocation X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src, int shift_amount) { + RegLocation rl_src, int shift_amount, int flags) { RegLocation rl_result = EvalLocWide(rl_dest, kCoreReg, true); if (cu_->target64) { OpKind op = static_cast<OpKind>(0); /* Make gcc happy */ @@ -2472,7 +2474,7 @@ RegLocation X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation } void X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_src, RegLocation rl_shift) { + RegLocation rl_src, RegLocation rl_shift, int flags) { // Per spec, we only care about low 6 bits of shift amount. int shift_amount = mir_graph_->ConstantValue(rl_shift) & 0x3f; if (shift_amount == 0) { @@ -2482,7 +2484,7 @@ void X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest } else if (shift_amount == 1 && (opcode == Instruction::SHL_LONG || opcode == Instruction::SHL_LONG_2ADDR)) { // Need to handle this here to avoid calling StoreValueWide twice. - GenArithOpLong(Instruction::ADD_LONG, rl_dest, rl_src, rl_src); + GenArithOpLong(Instruction::ADD_LONG, rl_dest, rl_src, rl_src, flags); return; } if (PartiallyIntersects(rl_src, rl_dest)) { @@ -2490,12 +2492,13 @@ void X86Mir2Lir::GenShiftImmOpLong(Instruction::Code opcode, RegLocation rl_dest return; } rl_src = LoadValueWide(rl_src, kCoreReg); - RegLocation rl_result = GenShiftImmOpLong(opcode, rl_dest, rl_src, shift_amount); + RegLocation rl_result = GenShiftImmOpLong(opcode, rl_dest, rl_src, shift_amount, flags); StoreValueWide(rl_dest, rl_result); } void X86Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, - RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2) { + RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2, + int flags) { bool isConstSuccess = false; switch (opcode) { case Instruction::ADD_LONG: @@ -2514,7 +2517,7 @@ void X86Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, if (rl_src2.is_const) { isConstSuccess = GenLongLongImm(rl_dest, rl_src1, rl_src2, opcode); } else { - GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); isConstSuccess = true; } break; @@ -2540,7 +2543,7 @@ void X86Mir2Lir::GenArithImmOpLong(Instruction::Code opcode, if (!isConstSuccess) { // Default - bail to non-const handler. - GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2); + GenArithOpLong(opcode, rl_dest, rl_src1, rl_src2, flags); } } @@ -2912,7 +2915,7 @@ void X86Mir2Lir::GenInstanceofFinal(bool use_declaring_class, uint32_t type_idx, } void X86Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, - RegLocation rl_lhs, RegLocation rl_rhs) { + RegLocation rl_lhs, RegLocation rl_rhs, int flags) { OpKind op = kOpBkpt; bool is_div_rem = false; bool unary = false; @@ -3017,7 +3020,7 @@ void X86Mir2Lir::GenArithOpInt(Instruction::Code opcode, RegLocation rl_dest, // Get the div/rem stuff out of the way. if (is_div_rem) { - rl_result = GenDivRem(rl_dest, rl_lhs, rl_rhs, op == kOpDiv, true); + rl_result = GenDivRem(rl_dest, rl_lhs, rl_rhs, op == kOpDiv, flags); StoreValue(rl_dest, rl_result); return; } diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc index 2ef4c21..79d5eeb 100755 --- a/compiler/dex/quick/x86/target_x86.cc +++ b/compiler/dex/quick/x86/target_x86.cc @@ -2166,7 +2166,7 @@ void X86Mir2Lir::GenAddReduceVector(BasicBlock *bb, MIR *mir) { NewLIR2(kX86MovdrxRR, temp_loc.reg.GetHighReg(), vector_src.GetReg()); } - GenArithOpLong(Instruction::ADD_LONG_2ADDR, rl_dest, temp_loc, temp_loc); + GenArithOpLong(Instruction::ADD_LONG_2ADDR, rl_dest, temp_loc, temp_loc, mir->optimization_flags); } else if (opsize == kSignedByte || opsize == kUnsignedByte) { RegStorage rs_tmp = Get128BitRegister(AllocTempDouble()); NewLIR2(kX86PxorRR, rs_tmp.GetReg(), rs_tmp.GetReg()); |