Merge "Remove Iceland." into dalvik-dev
diff --git a/src/compiler/codegen/arm/int_arm.cc b/src/compiler/codegen/arm/int_arm.cc
index 1447aec..e927b13 100644
--- a/src/compiler/codegen/arm/int_arm.cc
+++ b/src/compiler/codegen/arm/int_arm.cc
@@ -186,6 +186,23 @@
 {
   RegLocation rl_result;
   RegLocation rl_src = GetSrc(cu, mir, 0);
+  // Temporary debugging code
+  int dest_sreg = mir->ssa_rep->defs[0];
+  if ((dest_sreg < 0) || (dest_sreg >= cu->num_ssa_regs)) {
+    LOG(INFO) << "Bad target sreg: " << dest_sreg << ", in "
+              << PrettyMethod(cu->method_idx,*cu->dex_file);
+    LOG(INFO) << "at dex offset 0x" << std::hex << mir->offset;
+    LOG(INFO) << "vreg = " << SRegToVReg(cu, dest_sreg);
+    LOG(INFO) << "num uses = " << mir->ssa_rep->num_uses;
+    if (mir->ssa_rep->num_uses == 1) {
+      LOG(INFO) << "CONST case, vals = " << mir->dalvikInsn.vB << ", " << mir->dalvikInsn.vC;
+    } else {
+      LOG(INFO) << "MOVE case, operands = " << mir->ssa_rep->uses[1] << ", "
+                << mir->ssa_rep->uses[2];
+    }
+    CHECK(false) << "Invalid target sreg on Select.";
+  }
+  // End temporary debugging code
   RegLocation rl_dest = GetDest(cu, mir);
   rl_src = LoadValue(cu, rl_src, kCoreReg);
   if (mir->ssa_rep->num_uses == 1) {
diff --git a/src/compiler/dataflow.cc b/src/compiler/dataflow.cc
index 7505f6c..2ce16a4 100644
--- a/src/compiler/dataflow.cc
+++ b/src/compiler/dataflow.cc
@@ -1791,7 +1791,7 @@
           if (bb->taken->dominates_return) {
             mir->optimization_flags |= MIR_IGNORE_SUSPEND_CHECK;
             if (cu->verbose) {
-              LOG(INFO) << "Suppressed suspend check at 0x" << std::hex << mir->offset;
+              LOG(INFO) << "Suppressed suspend check on branch to return at 0x" << std::hex << mir->offset;
             }
           }
           break;
@@ -1819,10 +1819,16 @@
          * transfers to the rejoin block and the fall_though edge goes to a block that
          * unconditionally falls through to the rejoin block.
          */
-
         if ((tk_ft == NULL) && (ft_tk == NULL) && (tk_tk == ft_ft) &&
             (Predecessors(tk) == 1) && (Predecessors(ft) == 1)) {
-          // Okay - we have the basic diamond shape.  Are the block bodies something we can handle?
+          /*
+           * Okay - we have the basic diamond shape.  At the very least, we can eliminate the
+           * suspend check on the taken-taken branch back to the join point.
+           */
+          if (SelectKind(tk->last_mir_insn) == kSelectGoto) {
+              tk->last_mir_insn->optimization_flags |= (MIR_IGNORE_SUSPEND_CHECK);
+          }
+          // Are the block bodies something we can handle?
           if ((ft->first_mir_insn == ft->last_mir_insn) &&
               (tk->first_mir_insn != tk->last_mir_insn) &&
               (tk->first_mir_insn->next == tk->last_mir_insn) &&
@@ -1833,7 +1839,9 @@
             // Almost there.  Are the instructions targeting the same vreg?
             MIR* if_true = tk->first_mir_insn;
             MIR* if_false = ft->first_mir_insn;
-            if (if_true->dalvikInsn.vA == if_false->dalvikInsn.vA) {
+            // It's possible that the target of the select isn't used - skip those (rare) cases.
+            MIR* phi = FindPhi(cu, tk_tk, if_true->ssa_rep->defs[0]);
+            if ((phi != NULL) && (if_true->dalvikInsn.vA == if_false->dalvikInsn.vA)) {
               /*
                * We'll convert the IF_EQZ/IF_NEZ to a SELECT.  We need to find the
                * Phi node in the merge block and delete it (while using the SSA name
@@ -1888,39 +1896,33 @@
                * name of the "true" path, delete the SSA name of the "false" path from the
                * Phi node (and fix up the incoming arc list).
                */
-              MIR* phi = FindPhi(cu, tk_tk, if_true->ssa_rep->defs[0]);
-              if (phi != NULL) {
-                if (phi->ssa_rep->num_uses == 2) {
-                  mir->ssa_rep->defs[0] = phi->ssa_rep->defs[0];
-                  phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
-                } else {
-                  int dead_def = if_false->ssa_rep->defs[0];
-                  int live_def = if_true->ssa_rep->defs[0];
-                  mir->ssa_rep->defs[0] = live_def;
-                  int* incoming = reinterpret_cast<int*>(phi->dalvikInsn.vB);
-                  for (int i = 0; i < phi->ssa_rep->num_uses; i++) {
-                    if (phi->ssa_rep->uses[i] == live_def) {
-                      incoming[i] = bb->id;
-                    }
-                  }
-                  for (int i = 0; i < phi->ssa_rep->num_uses; i++) {
-                    if (phi->ssa_rep->uses[i] == dead_def) {
-                      int last_slot = phi->ssa_rep->num_uses - 1;
-                      phi->ssa_rep->uses[i] = phi->ssa_rep->uses[last_slot];
-                      incoming[i] = incoming[last_slot];
-                    }
+              if (phi->ssa_rep->num_uses == 2) {
+                mir->ssa_rep->defs[0] = phi->ssa_rep->defs[0];
+                phi->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
+              } else {
+                int dead_def = if_false->ssa_rep->defs[0];
+                int live_def = if_true->ssa_rep->defs[0];
+                mir->ssa_rep->defs[0] = live_def;
+                int* incoming = reinterpret_cast<int*>(phi->dalvikInsn.vB);
+                for (int i = 0; i < phi->ssa_rep->num_uses; i++) {
+                  if (phi->ssa_rep->uses[i] == live_def) {
+                    incoming[i] = bb->id;
                   }
                 }
-                phi->ssa_rep->num_uses--;
+                for (int i = 0; i < phi->ssa_rep->num_uses; i++) {
+                  if (phi->ssa_rep->uses[i] == dead_def) {
+                    int last_slot = phi->ssa_rep->num_uses - 1;
+                    phi->ssa_rep->uses[i] = phi->ssa_rep->uses[last_slot];
+                    incoming[i] = incoming[last_slot];
+                  }
+                }
               }
+              phi->ssa_rep->num_uses--;
               bb->taken = NULL;
               tk->block_type = kDead;
               for (MIR* tmir = ft->first_mir_insn; tmir != NULL; tmir = tmir->next) {
                 tmir->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
               }
-            } else {
-              // At least we can eliminate the suspend check on the backwards branch.
-              tk->last_mir_insn->optimization_flags |= (MIR_IGNORE_SUSPEND_CHECK);
             }
           }
         }
diff --git a/src/utils.cc b/src/utils.cc
index 6b93da8..0416e37 100644
--- a/src/utils.cc
+++ b/src/utils.cc
@@ -312,6 +312,9 @@
 }
 
 std::string PrettyField(uint32_t field_idx, const DexFile& dex_file, bool with_type) {
+  if (field_idx >= dex_file.NumFieldIds()) {
+    return StringPrintf("<<invalid-field-idx-%d>>", field_idx);
+  }
   const DexFile::FieldId& field_id = dex_file.GetFieldId(field_idx);
   std::string result;
   if (with_type) {
@@ -325,6 +328,9 @@
 }
 
 std::string PrettyType(uint32_t type_idx, const DexFile& dex_file) {
+  if (type_idx >= dex_file.NumTypeIds()) {
+    return StringPrintf("<<invalid-type-idx-%d>>", type_idx);
+  }
   const DexFile::TypeId& type_id = dex_file.GetTypeId(type_idx);
   return PrettyDescriptor(dex_file.GetTypeDescriptor(type_id));
 }
@@ -383,6 +389,9 @@
 }
 
 std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with_signature) {
+  if (method_idx >= dex_file.NumMethodIds()) {
+    return StringPrintf("<<invalid-method-idx-%d>>", method_idx);
+  }
   const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
   std::string result(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(method_id)));
   result += '.';