From: Andreas Gampe Date: Sat, 26 Jul 2014 08:40:39 +0000 (-0700) Subject: ART: Special-case cb(n)z even for in-reg constant X-Git-Tag: android-x86-6.0-r1~145^2~2478^2~1^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=b07c1f9f4d6088ca2d4c1a10819e57b19acf7f22;p=android-x86%2Fart.git ART: Special-case cb(n)z even for in-reg constant Call out to OpCmpImmBranch in GenCompareAndBranch if the constant is zero and we are testing == or !=, even when zero has been loaded to a register already. This avoids a register size mismatch on 64b architectures when basically doing a null check, and generally squashes a cmp + branch to a cbz or cbnz on Arm and Mips. X86 is not degraded. Bug: 16562601 Change-Id: I1997760f43dc186a84247ad30ae91053f71d102d --- diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index adc228cf4..b94e8166b 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -273,13 +273,25 @@ void Mir2Lir::GenCompareAndBranch(Instruction::Code opcode, RegLocation rl_src1, if (rl_src2.is_const) { // If it's already live in a register or not easily materialized, just keep going RegLocation rl_temp = UpdateLoc(rl_src2); + int32_t constant_value = mir_graph_->ConstantValue(rl_src2); if ((rl_temp.location == kLocDalvikFrame) && - InexpensiveConstantInt(mir_graph_->ConstantValue(rl_src2))) { + InexpensiveConstantInt(constant_value)) { // OK - convert this to a compare immediate and branch OpCmpImmBranch(cond, rl_src1.reg, mir_graph_->ConstantValue(rl_src2), taken); return; } + + // It's also commonly more efficient to have a test against zero with Eq/Ne. This is not worse + // for x86, and allows a cbz/cbnz for Arm and Mips. At the same time, it works around a register + // mismatch for 64b systems, where a reference is compared against null, as dex bytecode uses + // the 32b literal 0 for null. + if (constant_value == 0 && (cond == kCondEq || cond == kCondNe)) { + // Use the OpCmpImmBranch and ignore the value in the register. + OpCmpImmBranch(cond, rl_src1.reg, 0, taken); + return; + } } + rl_src2 = LoadValue(rl_src2); OpCmpBranch(cond, rl_src1.reg, rl_src2.reg, taken); }