More suspend check repair.
The previous fix to the suspend check optimization mechanism left
a bug in the handling of constant-folded branches.
Change-Id: Ib71f1cb9f17203bee26746006e568d448666962d
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 5732dce..86f6ee5 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -306,9 +306,6 @@
default:
LOG(FATAL) << "Unexpected opcode(" << insn->dalvikInsn.opcode << ") with kBranch set";
}
- if (target <= cur_offset) {
- insn->backwards_branch = true;
- }
BasicBlock *taken_block = FindBlock(target, /* split */ true, /* create */ true,
/* immed_pred_block_p */ &cur_block);
cur_block->taken = taken_block;
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 45e425b..af1ae44 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -232,8 +232,7 @@
*/
struct MIR {
DecodedInstruction dalvikInsn;
- uint16_t width;
- bool backwards_branch; // TODO: may be useful to make this an attribute flag word.
+ uint32_t width; // NOTE: only need 16 bits for width.
unsigned int offset;
int m_unit_index; // From which method was this MIR included
MIR* prev;
@@ -560,6 +559,14 @@
return special_case_;
}
+ bool IsBackedge(BasicBlock* branch_bb, BasicBlock* target_bb) {
+ return ((target_bb != NULL) && (target_bb->start_offset <= branch_bb->start_offset));
+ }
+
+ bool IsBackwardsBranch(BasicBlock* branch_bb) {
+ return IsBackedge(branch_bb, branch_bb->taken) || IsBackedge(branch_bb, branch_bb->fall_through);
+ }
+
void BasicBlockCombine();
void CodeLayout();
void DumpCheckStats();
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 82ba6e3..9f694de 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -311,7 +311,8 @@
case Instruction::IF_GTZ:
case Instruction::IF_LEZ:
// If we've got a backwards branch to return, no need to suspend check.
- if ((bb->taken->dominates_return) && (mir->backwards_branch)) {
+ if ((IsBackedge(bb, bb->taken) && bb->taken->dominates_return) ||
+ (IsBackedge(bb, bb->fall_through) && bb->fall_through->dominates_return)) {
mir->optimization_flags |= MIR_IGNORE_SUSPEND_CHECK;
if (cu_->verbose) {
LOG(INFO) << "Suppressed suspend check on branch to return at 0x" << std::hex << mir->offset;
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 8f42999..862c1d7 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -239,7 +239,7 @@
case Instruction::GOTO:
case Instruction::GOTO_16:
case Instruction::GOTO_32:
- if (mir->backwards_branch) {
+ if (mir_graph_->IsBackedge(bb, bb->taken)) {
GenSuspendTestAndBranch(opt_flags, &label_list[bb->taken->id]);
} else {
OpUnconditionalBranch(&label_list[bb->taken->id]);
@@ -277,13 +277,13 @@
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));
- if (is_taken && mir->backwards_branch) {
+ BasicBlock* target = is_taken ? bb->taken : bb->fall_through;
+ if (mir_graph_->IsBackedge(bb, target)) {
GenSuspendTest(opt_flags);
}
- int id = is_taken ? bb->taken->id : bb->fall_through->id;
- OpUnconditionalBranch(&label_list[id]);
+ OpUnconditionalBranch(&label_list[target->id]);
} else {
- if (mir->backwards_branch) {
+ if (mir_graph_->IsBackwardsBranch(bb)) {
GenSuspendTest(opt_flags);
}
GenCompareAndBranch(opcode, rl_src[0], rl_src[1], taken,
@@ -303,13 +303,13 @@
// 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);
- if (is_taken && mir->backwards_branch) {
+ BasicBlock* target = is_taken ? bb->taken : bb->fall_through;
+ if (mir_graph_->IsBackedge(bb, target)) {
GenSuspendTest(opt_flags);
}
- int id = is_taken ? bb->taken->id : bb->fall_through->id;
- OpUnconditionalBranch(&label_list[id]);
+ OpUnconditionalBranch(&label_list[target->id]);
} else {
- if (mir->backwards_branch) {
+ if (mir_graph_->IsBackwardsBranch(bb)) {
GenSuspendTest(opt_flags);
}
GenCompareZeroAndBranch(opcode, rl_src[0], taken, fall_through);