summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2013-12-19 14:33:59 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2013-12-19 14:34:00 +0000
commit0da9089a855fdbc96e3fc0ff0a881c0d25764262 (patch)
treeef84f25b05163c7bd5414c1a89996e1d59682768
parent64763b9b42bdb96c5d1e48d10223c7b96c1f73c4 (diff)
parent412d4f833d8c6b43ef9725cda15bc97012d9ecdf (diff)
downloadandroid_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.h2
-rw-r--r--compiler/dex/quick/x86/int_x86.cc64
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";