diff options
author | Vladimir Marko <vmarko@google.com> | 2013-12-19 14:33:59 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-12-19 14:34:00 +0000 |
commit | 0da9089a855fdbc96e3fc0ff0a881c0d25764262 (patch) | |
tree | ef84f25b05163c7bd5414c1a89996e1d59682768 | |
parent | 64763b9b42bdb96c5d1e48d10223c7b96c1f73c4 (diff) | |
parent | 412d4f833d8c6b43ef9725cda15bc97012d9ecdf (diff) | |
download | android_art-0da9089a855fdbc96e3fc0ff0a881c0d25764262.tar.gz android_art-0da9089a855fdbc96e3fc0ff0a881c0d25764262.tar.bz2 android_art-0da9089a855fdbc96e3fc0ff0a881c0d25764262.zip |
Merge "Improve x86 Fused long compare to literal"
-rw-r--r-- | compiler/dex/quick/x86/codegen_x86.h | 2 | ||||
-rw-r--r-- | compiler/dex/quick/x86/int_x86.cc | 64 |
2 files changed, 65 insertions, 1 deletions
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 484d0cc831..22c4452991 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -209,6 +209,8 @@ class X86Mir2Lir : public Mir2Lir { int scale, int table_or_disp); void EmitMacro(const X86EncodingMap* entry, uint8_t reg, int offset); void EmitUnimplemented(const X86EncodingMap* entry, LIR* lir); + void GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, + int64_t val, ConditionCode ccode); }; } // namespace art diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 8ff9ded457..56cf7e96e3 100644 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -183,11 +183,23 @@ void X86Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { LIR* taken = &block_label_list_[bb->taken]; RegLocation rl_src1 = mir_graph_->GetSrcWide(mir, 0); RegLocation rl_src2 = mir_graph_->GetSrcWide(mir, 2); + ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); + + if (rl_src1.is_const) { + std::swap(rl_src1, rl_src2); + ccode = FlipComparisonOrder(ccode); + } + if (rl_src2.is_const) { + // Do special compare/branch against simple const operand + int64_t val = mir_graph_->ConstantValueWide(rl_src2); + GenFusedLongCmpImmBranch(bb, rl_src1, val, ccode); + return; + } + FlushAllRegs(); LockCallTemps(); // Prepare for explicit register usage LoadValueDirectWideFixed(rl_src1, r0, r1); LoadValueDirectWideFixed(rl_src2, r2, r3); - ConditionCode ccode = static_cast<ConditionCode>(mir->dalvikInsn.arg[0]); // Swap operands and condition code to prevent use of zero flag. if (ccode == kCondLe || ccode == kCondGt) { // Compute (r3:r2) = (r3:r2) - (r1:r0) @@ -218,6 +230,56 @@ void X86Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { OpCondBranch(ccode, taken); } +void X86Mir2Lir::GenFusedLongCmpImmBranch(BasicBlock* bb, RegLocation rl_src1, + int64_t val, ConditionCode ccode) { + int32_t val_lo = Low32Bits(val); + int32_t val_hi = High32Bits(val); + LIR* taken = &block_label_list_[bb->taken]; + LIR* not_taken = &block_label_list_[bb->fall_through]; + rl_src1 = LoadValueWide(rl_src1, kCoreReg); + int32_t low_reg = rl_src1.low_reg; + int32_t high_reg = rl_src1.high_reg; + + if (val == 0 && (ccode == kCondEq || ccode == kCondNe)) { + int t_reg = AllocTemp(); + OpRegRegReg(kOpOr, t_reg, low_reg, high_reg); + FreeTemp(t_reg); + OpCondBranch(ccode, taken); + return; + } + + OpRegImm(kOpCmp, high_reg, val_hi); + switch (ccode) { + case kCondEq: + case kCondNe: + OpCondBranch(kCondNe, (ccode == kCondEq) ? not_taken : taken); + break; + case kCondLt: + OpCondBranch(kCondLt, taken); + OpCondBranch(kCondGt, not_taken); + ccode = kCondUlt; + break; + case kCondLe: + OpCondBranch(kCondLt, taken); + OpCondBranch(kCondGt, not_taken); + ccode = kCondLs; + break; + case kCondGt: + OpCondBranch(kCondGt, taken); + OpCondBranch(kCondLt, not_taken); + ccode = kCondHi; + break; + case kCondGe: + OpCondBranch(kCondGt, taken); + OpCondBranch(kCondLt, not_taken); + ccode = kCondUge; + break; + default: + LOG(FATAL) << "Unexpected ccode: " << ccode; + } + OpCmpImmBranch(ccode, low_reg, val_lo, taken); +} + RegLocation X86Mir2Lir::GenDivRemLit(RegLocation rl_dest, int reg_lo, int lit, bool is_div) { LOG(FATAL) << "Unexpected use of GenDivRemLit for x86"; |