diff options
-rw-r--r-- | compiler/dex/mir_optimization.cc | 62 | ||||
-rw-r--r-- | compiler/dex/quick/codegen_util.cc | 22 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.cc | 43 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 1 |
4 files changed, 72 insertions, 56 deletions
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc index 1f630f78bb..55f2abcd3f 100644 --- a/compiler/dex/mir_optimization.cc +++ b/compiler/dex/mir_optimization.cc @@ -399,6 +399,28 @@ CompilerTemp* MIRGraph::GetNewCompilerTemp(CompilerTempType ct_type, bool wide) return compiler_temp; } +static 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; + UNREACHABLE(); + } + return is_taken; +} + /* Do some MIR-level extended basic block optimizations */ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) { if (bb->block_type == kDead) { @@ -424,6 +446,46 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) { // Look for interesting opcodes, skip otherwise Instruction::Code opcode = mir->dalvikInsn.opcode; switch (opcode) { + case Instruction::IF_EQ: + case Instruction::IF_NE: + case Instruction::IF_LT: + case Instruction::IF_GE: + case Instruction::IF_GT: + case Instruction::IF_LE: + if (!IsConst(mir->ssa_rep->uses[1])) { + break; + } + FALLTHROUGH_INTENDED; + case Instruction::IF_EQZ: + case Instruction::IF_NEZ: + case Instruction::IF_LTZ: + case Instruction::IF_GEZ: + case Instruction::IF_GTZ: + case Instruction::IF_LEZ: + // Result known at compile time? + if (IsConst(mir->ssa_rep->uses[0])) { + int32_t rhs = (mir->ssa_rep->num_uses == 2) ? ConstantValue(mir->ssa_rep->uses[1]) : 0; + bool is_taken = EvaluateBranch(opcode, ConstantValue(mir->ssa_rep->uses[0]), rhs); + BasicBlockId edge_to_kill = is_taken ? bb->fall_through : bb->taken; + if (is_taken) { + // Replace with GOTO. + bb->fall_through = NullBasicBlockId; + mir->dalvikInsn.opcode = Instruction::GOTO; + mir->dalvikInsn.vA = + IsInstructionIfCc(opcode) ? mir->dalvikInsn.vC : mir->dalvikInsn.vB; + } else { + // Make NOP. + bb->taken = NullBasicBlockId; + mir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + } + mir->ssa_rep->num_uses = 0; + BasicBlock* successor_to_unlink = GetBasicBlock(edge_to_kill); + successor_to_unlink->ErasePredecessor(bb->id); + if (successor_to_unlink->predecessors.empty()) { + successor_to_unlink->KillUnreachable(this); + } + } + break; case Instruction::CMPL_FLOAT: case Instruction::CMPL_DOUBLE: case Instruction::CMPG_FLOAT: diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index 1cde01e244..58bcee2124 100644 --- a/compiler/dex/quick/codegen_util.cc +++ b/compiler/dex/quick/codegen_util.cc @@ -922,28 +922,6 @@ void Mir2Lir::MarkBoundary(DexOffset offset, const char* inst_str) { NewLIR1(kPseudoDalvikByteCodeBoundary, WrapPointer(ArenaStrdup(inst_str))); } -bool Mir2Lir::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; - UNREACHABLE(); - } - return is_taken; -} - // Convert relation of src1/src2 to src2/src1 ConditionCode Mir2Lir::FlipComparisonOrder(ConditionCode before) { ConditionCode res; diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 0d30927679..68856cdce0 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -657,24 +657,12 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::IF_GT: case Instruction::IF_LE: { LIR* taken = &label_list[bb->taken]; - // Result known at compile time? - if (rl_src[0].is_const && rl_src[1].is_const) { - bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg), - mir_graph_->ConstantValue(rl_src[1].orig_sreg)); - BasicBlockId target_id = is_taken ? bb->taken : bb->fall_through; - if (mir_graph_->IsBackedge(bb, target_id) && - (kLeafOptimization || !mir_graph_->HasSuspendTestBetween(bb, target_id))) { - GenSuspendTest(opt_flags); - } - OpUnconditionalBranch(&label_list[target_id]); - } else { - if (mir_graph_->IsBackwardsBranch(bb) && - (kLeafOptimization || !mir_graph_->HasSuspendTestBetween(bb, bb->taken) || - !mir_graph_->HasSuspendTestBetween(bb, bb->fall_through))) { - GenSuspendTest(opt_flags); - } - GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken); + if (mir_graph_->IsBackwardsBranch(bb) && + (kLeafOptimization || !mir_graph_->HasSuspendTestBetween(bb, bb->taken) || + !mir_graph_->HasSuspendTestBetween(bb, bb->fall_through))) { + GenSuspendTest(opt_flags); } + GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken); break; } case Instruction::IF_EQZ: @@ -684,23 +672,12 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::IF_GTZ: case Instruction::IF_LEZ: { LIR* taken = &label_list[bb->taken]; - // Result known at compile time? - if (rl_src[0].is_const) { - bool is_taken = EvaluateBranch(opcode, mir_graph_->ConstantValue(rl_src[0].orig_sreg), 0); - BasicBlockId target_id = is_taken ? bb->taken : bb->fall_through; - if (mir_graph_->IsBackedge(bb, target_id) && - (kLeafOptimization || !mir_graph_->HasSuspendTestBetween(bb, target_id))) { - GenSuspendTest(opt_flags); - } - OpUnconditionalBranch(&label_list[target_id]); - } else { - if (mir_graph_->IsBackwardsBranch(bb) && - (kLeafOptimization || !mir_graph_->HasSuspendTestBetween(bb, bb->taken) || - !mir_graph_->HasSuspendTestBetween(bb, bb->fall_through))) { - GenSuspendTest(opt_flags); - } - GenCompareZeroAndBranch(opcode, rl_src[0], taken); + if (mir_graph_->IsBackwardsBranch(bb) && + (kLeafOptimization || !mir_graph_->HasSuspendTestBetween(bb, bb->taken) || + !mir_graph_->HasSuspendTestBetween(bb, bb->fall_through))) { + GenSuspendTest(opt_flags); } + GenCompareZeroAndBranch(opcode, rl_src[0], taken); break; } diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 6847717d8b..88b260c0eb 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -666,7 +666,6 @@ class Mir2Lir : public Backend { void MarkBoundary(DexOffset offset, const char* inst_str); void NopLIR(LIR* lir); void UnlinkLIR(LIR* lir); - bool EvaluateBranch(Instruction::Code opcode, int src1, int src2); bool IsInexpensiveConstant(RegLocation rl_src); ConditionCode FlipComparisonOrder(ConditionCode before); ConditionCode NegateComparison(ConditionCode before); |