From b07c1f9f4d6088ca2d4c1a10819e57b19acf7f22 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Sat, 26 Jul 2014 01:40:39 -0700 Subject: [PATCH] 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 --- compiler/dex/quick/gen_common.cc | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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); } -- 2.11.0