Compiler: GBC fix, CFG dump enhancements
Repaired some GBC generation bit rot, fixed a syntax error in
.dot cfg file generation, enhanced cfg generation to work before
SSA renaming and added new cfg dump points.
Change-Id: Id73b479209ea4d963810f67bde0ed502ed7361d3
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) {