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);