diff options
author | Andreas Gampe <agampe@google.com> | 2014-07-15 17:44:31 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-07-15 00:27:03 +0000 |
commit | 524e5e3815d2b16ee77beda9976b7ec3aa54aba6 (patch) | |
tree | 09bf29934a678614442d0760c72c211a30e23533 | |
parent | 07b8441303ea82fca3cb85d71ecf8752d73cedd7 (diff) | |
parent | 9522af985466b2a05ef5cdede0808777dea7236e (diff) | |
download | art-524e5e3815d2b16ee77beda9976b7ec3aa54aba6.tar.gz art-524e5e3815d2b16ee77beda9976b7ec3aa54aba6.tar.bz2 art-524e5e3815d2b16ee77beda9976b7ec3aa54aba6.zip |
Merge "ART: Squash a cmp w/ zero and b.ls to cbz (ARM/ARM64)"
-rw-r--r-- | compiler/dex/quick/arm/int_arm.cc | 20 | ||||
-rw-r--r-- | compiler/dex/quick/arm64/int_arm64.cc | 23 |
2 files changed, 31 insertions, 12 deletions
diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index f4ea592781..2fcc3a5abc 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -341,7 +341,7 @@ void ArmMir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { * is responsible for setting branch target field. */ LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) { - LIR* branch; + LIR* branch = nullptr; ArmConditionCode arm_cond = ArmConditionEncoding(cond); /* * A common use of OpCmpImmBranch is for null checks, and using the Thumb 16-bit @@ -354,14 +354,22 @@ LIR* ArmMir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_va */ bool skip = ((target != NULL) && (target->opcode == kPseudoThrowTarget)); skip &= ((cu_->code_item->insns_size_in_code_units_ - current_dalvik_offset_) > 64); - if (!skip && reg.Low8() && (check_value == 0) && - ((arm_cond == kArmCondEq) || (arm_cond == kArmCondNe))) { - branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, - reg.GetReg(), 0); - } else { + if (!skip && reg.Low8() && (check_value == 0)) { + if (arm_cond == kArmCondEq || arm_cond == kArmCondNe) { + branch = NewLIR2((arm_cond == kArmCondEq) ? kThumb2Cbz : kThumb2Cbnz, + reg.GetReg(), 0); + } else if (arm_cond == kArmCondLs) { + // kArmCondLs is an unsigned less or equal. A comparison r <= 0 is then the same as cbz. + // This case happens for a bounds check of array[0]. + branch = NewLIR2(kThumb2Cbz, reg.GetReg(), 0); + } + } + + if (branch == nullptr) { OpRegImm(kOpCmp, reg, check_value); branch = NewLIR2(kThumbBCond, 0, arm_cond); } + branch->target = target; return branch; } diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc index 2650892975..6dc4a7ab51 100644 --- a/compiler/dex/quick/arm64/int_arm64.cc +++ b/compiler/dex/quick/arm64/int_arm64.cc @@ -269,16 +269,27 @@ void Arm64Mir2Lir::GenFusedLongCmpBranch(BasicBlock* bb, MIR* mir) { */ LIR* Arm64Mir2Lir::OpCmpImmBranch(ConditionCode cond, RegStorage reg, int check_value, LIR* target) { - LIR* branch; + LIR* branch = nullptr; ArmConditionCode arm_cond = ArmConditionEncoding(cond); - if (check_value == 0 && (arm_cond == kArmCondEq || arm_cond == kArmCondNe)) { - ArmOpcode opcode = (arm_cond == kArmCondEq) ? kA64Cbz2rt : kA64Cbnz2rt; - ArmOpcode wide = reg.Is64Bit() ? WIDE(0) : UNWIDE(0); - branch = NewLIR2(opcode | wide, reg.GetReg(), 0); - } else { + if (check_value == 0) { + if (arm_cond == kArmCondEq || arm_cond == kArmCondNe) { + ArmOpcode opcode = (arm_cond == kArmCondEq) ? kA64Cbz2rt : kA64Cbnz2rt; + ArmOpcode wide = reg.Is64Bit() ? WIDE(0) : UNWIDE(0); + branch = NewLIR2(opcode | wide, reg.GetReg(), 0); + } else if (arm_cond == kArmCondLs) { + // kArmCondLs is an unsigned less or equal. A comparison r <= 0 is then the same as cbz. + // This case happens for a bounds check of array[0]. + ArmOpcode opcode = kA64Cbz2rt; + ArmOpcode wide = reg.Is64Bit() ? WIDE(0) : UNWIDE(0); + branch = NewLIR2(opcode | wide, reg.GetReg(), 0); + } + } + + if (branch == nullptr) { OpRegImm(kOpCmp, reg, check_value); branch = NewLIR2(kA64B2ct, arm_cond, 0); } + branch->target = target; return branch; } |