Merge "Compiler: GBC fix, CFG dump enhancements" into dalvik-dev
diff --git a/src/compiler/codegen/gen_loadstore.cc b/src/compiler/codegen/gen_loadstore.cc
index eec74af..6c16d40 100644
--- a/src/compiler/codegen/gen_loadstore.cc
+++ b/src/compiler/codegen/gen_loadstore.cc
@@ -46,15 +46,18 @@
     int pmap_index = SRegToPMap(cu, rl_dest.s_reg_low);
     if (cu->promotion_map[pmap_index].fp_location == kLocPhysReg) {
       // Now, determine if this vreg is ever used as a reference.  If not, we're done.
-      bool used_as_reference = false;
-      int base_vreg = SRegToVReg(cu, rl_dest.s_reg_low);
-      for (int i = 0; !used_as_reference && (i < cu->num_ssa_regs); i++) {
-        if (SRegToVReg(cu, cu->reg_location[i].s_reg_low) == base_vreg) {
-          used_as_reference |= cu->reg_location[i].ref;
+      if (!cu->gen_bitcode) {
+        // TUNING: We no longer have this info for QuickGBC - assume the worst
+        bool used_as_reference = false;
+        int base_vreg = SRegToVReg(cu, rl_dest.s_reg_low);
+        for (int i = 0; !used_as_reference && (i < cu->num_ssa_regs); i++) {
+          if (SRegToVReg(cu, cu->reg_location[i].s_reg_low) == base_vreg) {
+            used_as_reference |= cu->reg_location[i].ref;
+          }
         }
-      }
-      if (!used_as_reference) {
-        return;
+        if (!used_as_reference) {
+          return;
+        }
       }
       if (cu->promotion_map[pmap_index].core_location == kLocPhysReg) {
         // Promoted - just copy in a zero
diff --git a/src/compiler/codegen/mir_to_gbc.cc b/src/compiler/codegen/mir_to_gbc.cc
index 6758bb9..e1e1fb1 100644
--- a/src/compiler/codegen/mir_to_gbc.cc
+++ b/src/compiler/codegen/mir_to_gbc.cc
@@ -1643,6 +1643,9 @@
       if (rl_dest.high_word) {
         return;  // No Phi node - handled via low word
       }
+      // LLVM requires that all Phi nodes are at the beginning of the block
+      llvm::IRBuilderBase::InsertPoint ip = cu->irb->saveAndClearIP();
+      cu->irb->SetInsertPoint(llvm_bb);
       int* incoming = reinterpret_cast<int*>(mir->dalvikInsn.vB);
       llvm::Type* phi_type =
           LlvmTypeFromLocRec(cu, rl_dest);
@@ -1662,6 +1665,8 @@
         phi->addIncoming(GetLLVMValue(cu, loc.orig_sreg),
                          GetLLVMBlock(cu, it->second));
       }
+      // Now that Phi node is emitted, add definition at old insert point
+      cu->irb->restoreIP(ip);
       DefineValue(cu, phi, rl_dest.orig_sreg);
       break;
     }
@@ -1789,9 +1794,7 @@
             greenland::IntrinsicHelper::AllocaShadowFrame;
     llvm::Function* func = cu->intrinsic_helper->GetIntrinsicFunction(id);
     llvm::Value* entries = cu->irb->getInt32(cu->num_shadow_frame_entries);
-    llvm::Value* dalvik_regs = cu->irb->getInt32(cu->num_dalvik_registers);
-    llvm::Value* args[] = { entries, dalvik_regs };
-    cu->irb->CreateCall(func, args);
+    cu->irb->CreateCall(func, entries);
   } else if (bb->block_type == kExitBlock) {
     /*
      * Because of the differences between how MIR/LIR and llvm handle exit
diff --git a/src/compiler/compiler_utility.cc b/src/compiler/compiler_utility.cc
index 2e67902..0bce17c 100644
--- a/src/compiler/compiler_utility.cc
+++ b/src/compiler/compiler_utility.cc
@@ -674,7 +674,7 @@
                bb->id);
       break;
     default:
-      snprintf(name, BLOCK_NAME_LEN, "??_%d", bb->id);
+      snprintf(name, BLOCK_NAME_LEN, "_%d", bb->id);
       break;
   }
 }
diff --git a/src/compiler/dataflow.cc b/src/compiler/dataflow.cc
index 22135b1..03ede70 100644
--- a/src/compiler/dataflow.cc
+++ b/src/compiler/dataflow.cc
@@ -862,6 +862,10 @@
 // Similar to GetSSAName, but if ssa name represents an immediate show that as well.
 static std::string GetSSANameWithConst(const CompilationUnit* cu, int ssa_reg, bool singles_only)
 {
+  if (cu->reg_location == NULL) {
+    // Pre-SSA - just use the Dalvik vreg
+    return StringPrintf("v%d", ssa_reg);
+  }
   if (cu->reg_location[ssa_reg].is_const) {
     if (!singles_only && cu->reg_location[ssa_reg].wide) {
       int64_t immval = cu->constant_values[ssa_reg + 1];
@@ -940,8 +944,7 @@
         break;
       case Instruction::k22t:
         str.append(StringPrintf(" %s, %s,", GetSSANameWithConst(cu, ssa_rep->uses[0], false).c_str(),
-                   GetSSANameWithConst(cu, ssa_rep->uses[cu->reg_location[ssa_rep->uses[0]].wide
-                                       ? 2 : 1], false).c_str()));
+                   GetSSANameWithConst(cu, ssa_rep->uses[1], false).c_str()));
         offset = insn.vC;
         break;
       case Instruction::k10t:
@@ -967,7 +970,7 @@
     for (int i = 0; i < uses; i++) {
       str.append(
           StringPrintf(" %s", GetSSANameWithConst(cu, ssa_rep->uses[i], show_singles).c_str()));
-      if (!show_singles && cu->reg_location[i].wide) {
+      if (!show_singles && (cu->reg_location != NULL) && cu->reg_location[i].wide) {
         // For the listing, skip the high sreg.
         i++;
       }
diff --git a/src/compiler/frontend.cc b/src/compiler/frontend.cc
index d896e5b..9d30b6a 100644
--- a/src/compiler/frontend.cc
+++ b/src/compiler/frontend.cc
@@ -269,7 +269,7 @@
 }
 
 /* Dump the CFG into a DOT graph */
-void DumpCFG(CompilationUnit* cu, const char* dir_prefix)
+void DumpCFG(CompilationUnit* cu, const char* dir_prefix, bool all_blocks)
 {
   FILE* file;
   std::string fname(PrettyMethod(cu->method_idx, *cu->dex_file));
@@ -284,12 +284,12 @@
 
   fprintf(file, "  rankdir=TB\n");
 
-  int num_reachable_blocks = cu->num_reachable_blocks;
+  int num_blocks = all_blocks ? cu->num_blocks : cu->num_reachable_blocks;
   int idx;
   const GrowableList *block_list = &cu->block_list;
 
-  for (idx = 0; idx < num_reachable_blocks; idx++) {
-    int block_idx = cu->dfs_order.elem_list[idx];
+  for (idx = 0; idx < num_blocks; idx++) {
+    int block_idx = all_blocks ? idx : cu->dfs_order.elem_list[idx];
     BasicBlock *bb = reinterpret_cast<BasicBlock*>(GrowableListGetElement(block_list, block_idx));
     if (bb == NULL) break;
     if (bb->block_type == kDead) continue;
@@ -304,9 +304,13 @@
         fprintf(file, "    {block id %d\\l}%s\\\n", bb->id,
                 bb->first_mir_insn ? " | " : " ");
         for (mir = bb->first_mir_insn; mir; mir = mir->next) {
-            fprintf(file, "    {%04x %s\\l}%s\\\n", mir->offset,
+            int opcode = mir->dalvikInsn.opcode;
+            fprintf(file, "    {%04x %s %s %s\\l}%s\\\n", mir->offset,
                     mir->ssa_rep ? GetDalvikDisassembly(cu, mir) :
-                    Instruction::Name(mir->dalvikInsn.opcode),
+                    (opcode < kMirOpFirst) ?  Instruction::Name(mir->dalvikInsn.opcode) :
+                    extended_mir_op_names[opcode - kMirOpFirst],
+                    (mir->optimization_flags & MIR_IGNORE_RANGE_CHECK) != 0 ? " no_rangecheck" : " ",
+                    (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0 ? " no_nullcheck" : " ",
                     mir->next ? " | " : " ");
         }
         fprintf(file, "  }\"];\n\n");
@@ -386,13 +390,15 @@
     }
     fprintf(file, "\n");
 
-    /* Display the dominator tree */
-    GetBlockName(bb, block_name1);
-    fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
-            block_name1, block_name1);
-    if (bb->i_dom) {
-      GetBlockName(bb->i_dom, block_name2);
-      fprintf(file, "  cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
+    if (cu->verbose) {
+      /* Display the dominator tree */
+      GetBlockName(bb, block_name1);
+      fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
+              block_name1, block_name1);
+      if (bb->i_dom) {
+        GetBlockName(bb->i_dom, block_name2);
+        fprintf(file, "  cfg%s:s -> cfg%s:n\n\n", block_name2, block_name1);
+      }
     }
   }
   fprintf(file, "}\n");
@@ -432,7 +438,7 @@
       char block_name1[BLOCK_NAME_LEN], block_name2[BLOCK_NAME_LEN];
       GetBlockName(bb, block_name1);
       GetBlockName(pred_bb, block_name2);
-      DumpCFG(cu, "/sdcard/cfg/");
+      DumpCFG(cu, "/sdcard/cfg/", false);
       LOG(FATAL) << "Successor " << block_name1 << "not found from "
                  << block_name2;
     }
@@ -804,10 +810,6 @@
     cu->gen_bitcode = true;
   }
   DCHECK_NE(compiler_backend, kIceland);  // TODO: remove when Portable/Iceland merge complete
-  // TODO: remove this once x86 is tested
-  if (cu->gen_bitcode && (cu->instruction_set != kThumb2)) {
-    UNIMPLEMENTED(WARNING) << "GBC generation untested for non-Thumb targets";
-  }
   cu->llvm_info = llvm_info;
   /* Adjust this value accordingly once inlining is performed */
   cu->num_dalvik_registers = code_item->registers_size_;
@@ -1025,6 +1027,10 @@
     }
   }
 
+  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
+    DumpCFG(cu.get(), "/sdcard/1_post_parse_cfg/", true);
+  }
+
   if (!(cu->disable_opt & (1 << kSkipLargeMethodOptimization))) {
     if ((cu->num_blocks > MANY_BLOCKS) ||
         ((cu->num_blocks > MANY_BLOCKS_INITIALIZER) &&
@@ -1053,6 +1059,10 @@
   /* Do a code layout pass */
   CodeLayout(cu.get());
 
+  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
+    DumpCFG(cu.get(), "/sdcard/2_post_layout_cfg/", true);
+  }
+
   if (cu->enable_debug & (1 << kDebugVerifyDataflow)) {
     /* Verify if all blocks are connected as claimed */
     DataFlowAnalysisDispatcher(cu.get(), VerifyPredInfo, kAllNodes,
@@ -1062,6 +1072,10 @@
   /* Perform SSA transformation for the whole method */
   SSATransformation(cu.get());
 
+  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
+    DumpCFG(cu.get(), "/sdcard/3_post_ssa_cfg/", false);
+  }
+
   /* Do constant propagation */
   // TODO: Probably need to make these expandable to support new ssa names
   // introducted during MIR optimization passes
@@ -1082,12 +1096,25 @@
   /* Perform null check elimination */
   NullCheckElimination(cu.get());
 
+  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
+    DumpCFG(cu.get(), "/sdcard/4_post_nce_cfg/", false);
+  }
+
   /* Combine basic blocks where possible */
   BasicBlockCombine(cu.get());
 
+  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
+    DumpCFG(cu.get(), "/sdcard/5_post_bbcombine_cfg/", false);
+  }
+
   /* Do some basic block optimizations */
   BasicBlockOptimization(cu.get());
 
+  // Debugging only
+  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
+    DumpCFG(cu.get(), "/sdcard/6_post_bbo_cfg/", false);
+  }
+
   if (cu->enable_debug & (1 << kDebugDumpCheckStats)) {
     DumpCheckStats(cu.get());
   }
@@ -1124,11 +1151,6 @@
     }
   }
 
-  // Debugging only
-  if (cu->enable_debug & (1 << kDebugDumpCFG)) {
-    DumpCFG(cu.get(), "/sdcard/cfg/");
-  }
-
   /* Method is not empty */
   if (cu->first_lir_insn) {