From e6285f99a53a344efd6f8409ff5f43a3e80190db Mon Sep 17 00:00:00 2001 From: buzbee Date: Thu, 6 Dec 2012 15:57:46 -0800 Subject: Compiler: Take advantage of constant propagation The common frontend tracks constants via a constant propagation pass. When converting from MIR to GBC (for Portable) or LIR (for Quick), recognize constant arguments and select more efficient codegen forms. Note: we still have to flush constants to their associated vregs to support deoptimization. There's quite a bit of possible code size gain if we were to eliminate unnecessary stores or enhance the vmap table to explicitly represent the ranges over which Dalvik vregs are constant. Also some minor code refactoring related to array operations. There are sufficient architectural differences to make it worthwhile to have target-dependent aget/aput generators. On Arm, this is mostly beneficial to floating point array loads and stores. This CL yields a ~0.8% decrease in code size over the framework, and a nice pop to a few of the standard point benchmarks (linpack: ~10%, cm: ~11%, scimark: ~13% - no significant change to the others) Change-Id: I2337e1aa0622b34a34c3775f8b7dbf5e6969da3e --- src/compiler/codegen/codegen_util.cc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/compiler/codegen/codegen_util.cc') diff --git a/src/compiler/codegen/codegen_util.cc b/src/compiler/codegen/codegen_util.cc index bab5cd98c5..77a2269aaf 100644 --- a/src/compiler/codegen/codegen_util.cc +++ b/src/compiler/codegen/codegen_util.cc @@ -1074,4 +1074,27 @@ LIR* MarkBoundary(CompilationUnit* cu, int offset, const char* inst_str) return res; } +bool EvaluateBranch(Instruction::Code opcode, int32_t src1, int32_t src2) +{ + bool is_taken; + switch (opcode) { + case Instruction::IF_EQ: is_taken = (src1 == src2); break; + case Instruction::IF_NE: is_taken = (src1 != src2); break; + case Instruction::IF_LT: is_taken = (src1 < src2); break; + case Instruction::IF_GE: is_taken = (src1 >= src2); break; + case Instruction::IF_GT: is_taken = (src1 > src2); break; + case Instruction::IF_LE: is_taken = (src1 <= src2); break; + case Instruction::IF_EQZ: is_taken = (src1 == 0); break; + case Instruction::IF_NEZ: is_taken = (src1 != 0); break; + case Instruction::IF_LTZ: is_taken = (src1 < 0); break; + case Instruction::IF_GEZ: is_taken = (src1 >= 0); break; + case Instruction::IF_GTZ: is_taken = (src1 > 0); break; + case Instruction::IF_LEZ: is_taken = (src1 <= 0); break; + default: + LOG(FATAL) << "Unexpected opcode " << opcode; + is_taken = false; + } + return is_taken; +} + } // namespace art -- cgit v1.2.3-59-g8ed1b