summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Elliott Hughes <enh@google.com> 2013-11-26 20:14:20 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2013-11-26 20:14:21 +0000
commit83a9962f4062cd91e823a2a948aba3887cbe32aa (patch)
tree01ff0b0545450439200b81627bfc43ae60f414c2 /compiler
parent21be5b21017823b3785f94349e2e2b57d82431e6 (diff)
parent1da1e2fceb0030b4b76b43510b1710a9613e0c2e (diff)
Merge "More compile-time tuning"
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/dataflow_iterator-inl.h2
-rw-r--r--compiler/dex/dataflow_iterator.h4
-rw-r--r--compiler/dex/frontend.cc24
-rw-r--r--compiler/dex/mir_dataflow.cc112
-rw-r--r--compiler/dex/mir_graph.cc6
-rw-r--r--compiler/dex/mir_graph.h85
-rw-r--r--compiler/dex/mir_optimization.cc209
-rw-r--r--compiler/dex/portable/mir_to_gbc.cc2
-rw-r--r--compiler/dex/quick/arm/assemble_arm.cc1
-rw-r--r--compiler/dex/quick/local_optimizations.cc6
-rw-r--r--compiler/dex/quick/mips/assemble_mips.cc1
-rw-r--r--compiler/dex/quick/mir_to_lir.cc2
-rw-r--r--compiler/dex/quick/x86/assemble_x86.cc1
-rw-r--r--compiler/dex/vreg_analysis.cc490
14 files changed, 485 insertions, 460 deletions
diff --git a/compiler/dex/dataflow_iterator-inl.h b/compiler/dex/dataflow_iterator-inl.h
index 74f36ddd81..64e5fa64e3 100644
--- a/compiler/dex/dataflow_iterator-inl.h
+++ b/compiler/dex/dataflow_iterator-inl.h
@@ -37,6 +37,7 @@ inline BasicBlock* DataflowIterator::ForwardRepeatNext(bool had_change) {
BasicBlock* res = NULL;
if ((idx_ >= end_idx_) && changed_) {
idx_ = start_idx_;
+ repeats_++;
changed_ = false;
}
if (idx_ < end_idx_) {
@@ -62,6 +63,7 @@ inline BasicBlock* DataflowIterator::ReverseRepeatNext(bool had_change) {
BasicBlock* res = NULL;
if ((idx_ < 0) && changed_) {
idx_ = start_idx_;
+ repeats_++;
changed_ = false;
}
if (idx_ >= 0) {
diff --git a/compiler/dex/dataflow_iterator.h b/compiler/dex/dataflow_iterator.h
index 26e36653be..a0c1c123e7 100644
--- a/compiler/dex/dataflow_iterator.h
+++ b/compiler/dex/dataflow_iterator.h
@@ -37,6 +37,7 @@ namespace art {
class DataflowIterator {
public:
virtual ~DataflowIterator() {}
+ int32_t GetRepeatCount() { return repeats_; }
protected:
DataflowIterator(MIRGraph* mir_graph, int32_t start_idx, int32_t end_idx)
@@ -45,6 +46,7 @@ namespace art {
end_idx_(end_idx),
block_id_list_(NULL),
idx_(0),
+ repeats_(0),
changed_(false) {}
virtual BasicBlock* ForwardSingleNext() ALWAYS_INLINE;
@@ -52,11 +54,13 @@ namespace art {
virtual BasicBlock* ForwardRepeatNext(bool had_change) ALWAYS_INLINE;
virtual BasicBlock* ReverseRepeatNext(bool had_change) ALWAYS_INLINE;
+
MIRGraph* const mir_graph_;
const int32_t start_idx_;
const int32_t end_idx_;
GrowableArray<BasicBlockId>* block_id_list_;
int32_t idx_;
+ int32_t repeats_;
bool changed_;
}; // DataflowIterator
diff --git a/compiler/dex/frontend.cc b/compiler/dex/frontend.cc
index e53d63648b..197bba5a58 100644
--- a/compiler/dex/frontend.cc
+++ b/compiler/dex/frontend.cc
@@ -253,15 +253,15 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler,
cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx,
class_loader, dex_file);
+ cu.NewTimingSplit("MIROpt:CheckFilters");
#if !defined(ART_USE_PORTABLE_COMPILER)
if (cu.mir_graph->SkipCompilation(Runtime::Current()->GetCompilerFilter())) {
return NULL;
}
#endif
- cu.NewTimingSplit("MIROpt:CodeLayout");
-
/* Do a code layout pass */
+ cu.NewTimingSplit("MIROpt:CodeLayout");
cu.mir_graph->CodeLayout();
/* Perform SSA transformation for the whole method */
@@ -272,18 +272,23 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler,
cu.NewTimingSplit("MIROpt:ConstantProp");
cu.mir_graph->PropagateConstants();
+ cu.NewTimingSplit("MIROpt:InitRegLoc");
+ cu.mir_graph->InitRegLocations();
+
/* Count uses */
+ cu.NewTimingSplit("MIROpt:UseCount");
cu.mir_graph->MethodUseCount();
- /* Perform null check elimination */
- cu.NewTimingSplit("MIROpt:NullCheckElimination");
- cu.mir_graph->NullCheckElimination();
+ /* Perform null check elimination and type inference*/
+ cu.NewTimingSplit("MIROpt:NCE_TypeInference");
+ cu.mir_graph->NullCheckEliminationAndTypeInference();
/* Combine basic blocks where possible */
- cu.NewTimingSplit("MIROpt:BBOpt");
+ cu.NewTimingSplit("MIROpt:BBCombine");
cu.mir_graph->BasicBlockCombine();
/* Do some basic block optimizations */
+ cu.NewTimingSplit("MIROpt:BBOpt");
cu.mir_graph->BasicBlockOptimization();
if (cu.enable_debug & (1 << kDebugDumpCheckStats)) {
@@ -294,8 +299,8 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler,
cu.mir_graph->ShowOpcodeStats();
}
- /* Set up regLocation[] array to describe values - one for each ssa_name. */
- cu.mir_graph->BuildRegLocations();
+ /* Reassociate sreg names with original Dalvik vreg names. */
+ cu.mir_graph->RemapRegLocations();
CompiledMethod* result = NULL;
@@ -323,8 +328,9 @@ static CompiledMethod* CompileMethod(CompilerDriver& compiler,
cu.cg->Materialize();
- cu.NewTimingSplit("Cleanup");
+ cu.NewTimingSplit("Dedupe"); /* deduping takes up the vast majority of time in GetCompiledMethod(). */
result = cu.cg->GetCompiledMethod();
+ cu.NewTimingSplit("Cleanup");
if (result) {
VLOG(compiler) << "Compiled " << PrettyMethod(method_idx, dex_file);
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index d359ee2dfe..728d48ad70 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -29,7 +29,7 @@ namespace art {
* TODO - many optimization flags are incomplete - they will only limit the
* scope of optimizations but will not cause mis-optimizations.
*/
-const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
+const uint64_t MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
// 00 NOP
DF_NOP,
@@ -235,88 +235,88 @@ const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
DF_NOP,
// 44 AGET vAA, vBB, vCC
- DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C | DF_LVN,
// 45 AGET_WIDE vAA, vBB, vCC
- DF_DA | DF_A_WIDE | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_A_WIDE | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C | DF_LVN,
// 46 AGET_OBJECT vAA, vBB, vCC
- DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_A | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_A | DF_REF_B | DF_CORE_C | DF_LVN,
// 47 AGET_BOOLEAN vAA, vBB, vCC
- DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C | DF_LVN,
// 48 AGET_BYTE vAA, vBB, vCC
- DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C | DF_LVN,
// 49 AGET_CHAR vAA, vBB, vCC
- DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C | DF_LVN,
// 4A AGET_SHORT vAA, vBB, vCC
- DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C,
+ DF_DA | DF_UB | DF_UC | DF_NULL_CHK_0 | DF_RANGE_CHK_1 | DF_REF_B | DF_CORE_C | DF_LVN,
// 4B APUT vAA, vBB, vCC
- DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C | DF_LVN,
// 4C APUT_WIDE vAA, vBB, vCC
- DF_UA | DF_A_WIDE | DF_UB | DF_UC | DF_NULL_CHK_2 | DF_RANGE_CHK_3 | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_A_WIDE | DF_UB | DF_UC | DF_NULL_CHK_2 | DF_RANGE_CHK_3 | DF_REF_B | DF_CORE_C | DF_LVN,
// 4D APUT_OBJECT vAA, vBB, vCC
- DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_A | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_A | DF_REF_B | DF_CORE_C | DF_LVN,
// 4E APUT_BOOLEAN vAA, vBB, vCC
- DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C | DF_LVN,
// 4F APUT_BYTE vAA, vBB, vCC
- DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C | DF_LVN,
// 50 APUT_CHAR vAA, vBB, vCC
- DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C | DF_LVN,
// 51 APUT_SHORT vAA, vBB, vCC
- DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C,
+ DF_UA | DF_UB | DF_UC | DF_NULL_CHK_1 | DF_RANGE_CHK_2 | DF_REF_B | DF_CORE_C | DF_LVN,
// 52 IGET vA, vB, field@CCCC
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// 53 IGET_WIDE vA, vB, field@CCCC
- DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// 54 IGET_OBJECT vA, vB, field@CCCC
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B | DF_LVN,
// 55 IGET_BOOLEAN vA, vB, field@CCCC
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// 56 IGET_BYTE vA, vB, field@CCCC
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// 57 IGET_CHAR vA, vB, field@CCCC
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// 58 IGET_SHORT vA, vB, field@CCCC
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// 59 IPUT vA, vB, field@CCCC
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
// 5A IPUT_WIDE vA, vB, field@CCCC
- DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B,
+ DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B | DF_LVN,
// 5B IPUT_OBJECT vA, vB, field@CCCC
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B | DF_LVN,
// 5C IPUT_BOOLEAN vA, vB, field@CCCC
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
// 5D IPUT_BYTE vA, vB, field@CCCC
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
// 5E IPUT_CHAR vA, vB, field@CCCC
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
// 5F IPUT_SHORT vA, vB, field@CCCC
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
// 60 SGET vAA, field@BBBB
DF_DA | DF_UMS,
@@ -712,10 +712,10 @@ const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
DF_DA | DF_UB | DF_CORE_A | DF_CORE_B,
// E3 IGET_VOLATILE
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// E4 IPUT_VOLATILE
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_B | DF_LVN,
// E5 SGET_VOLATILE
DF_DA | DF_UMS,
@@ -724,13 +724,13 @@ const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
DF_UA | DF_UMS,
// E7 IGET_OBJECT_VOLATILE
- DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_REF_A | DF_REF_B | DF_LVN,
// E8 IGET_WIDE_VOLATILE
- DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B,
+ DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_REF_B | DF_LVN,
// E9 IPUT_WIDE_VOLATILE
- DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B,
+ DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_REF_B | DF_LVN,
// EA SGET_WIDE_VOLATILE
DF_DA | DF_A_WIDE | DF_UMS,
@@ -757,22 +757,22 @@ const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
DF_NOP,
// F2 IGET_QUICK
- DF_DA | DF_UB | DF_NULL_CHK_0,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_LVN,
// F3 IGET_WIDE_QUICK
- DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0,
+ DF_DA | DF_A_WIDE | DF_UB | DF_NULL_CHK_0 | DF_LVN,
// F4 IGET_OBJECT_QUICK
- DF_DA | DF_UB | DF_NULL_CHK_0,
+ DF_DA | DF_UB | DF_NULL_CHK_0 | DF_LVN,
// F5 IPUT_QUICK
- DF_UA | DF_UB | DF_NULL_CHK_1,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_LVN,
// F6 IPUT_WIDE_QUICK
- DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2,
+ DF_UA | DF_A_WIDE | DF_UB | DF_NULL_CHK_2 | DF_LVN,
// F7 IPUT_OBJECT_QUICK
- DF_UA | DF_UB | DF_NULL_CHK_1,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_LVN,
// F8 INVOKE_VIRTUAL_QUICK
DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
@@ -787,7 +787,7 @@ const int MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
DF_FORMAT_3RC | DF_NULL_CHK_OUT0 | DF_UMS,
// FC IPUT_OBJECT_VOLATILE
- DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B,
+ DF_UA | DF_UB | DF_NULL_CHK_1 | DF_REF_A | DF_REF_B | DF_LVN,
// FD SGET_OBJECT_VOLATILE
DF_DA | DF_REF_A | DF_UMS,
@@ -879,7 +879,7 @@ bool MIRGraph::FindLocalLiveIn(BasicBlock* bb) {
new (arena_) ArenaBitVector(arena_, cu_->num_dalvik_registers, false, kBitMapLiveIn);
for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
- int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+ uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
DecodedInstruction *d_insn = &mir->dalvikInsn;
if (df_attributes & DF_HAS_USES) {
@@ -994,7 +994,7 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) {
static_cast<struct SSARepresentation *>(arena_->Alloc(sizeof(SSARepresentation),
ArenaAllocator::kAllocDFInfo));
- int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+ uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
// If not a pseudo-op, note non-leaf or can throw
if (static_cast<int>(mir->dalvikInsn.opcode) <
@@ -1239,37 +1239,33 @@ bool MIRGraph::CountUses(struct BasicBlock* bb) {
if (bb->block_type != kDalvikByteCode) {
return false;
}
+ // Each level of nesting adds *100 to count, up to 3 levels deep.
+ uint32_t depth = std::min(3U, static_cast<uint32_t>(bb->nesting_depth));
+ uint32_t weight = std::max(1U, depth * 100);
for (MIR* mir = bb->first_mir_insn; (mir != NULL); mir = mir->next) {
if (mir->ssa_rep == NULL) {
continue;
}
- // Each level of nesting adds *100 to count, up to 3 levels deep.
- uint32_t depth = std::min(3U, static_cast<uint32_t>(bb->nesting_depth));
- uint32_t weight = std::max(1U, depth * 100);
for (int i = 0; i < mir->ssa_rep->num_uses; i++) {
int s_reg = mir->ssa_rep->uses[i];
raw_use_counts_.Increment(s_reg);
use_counts_.Put(s_reg, use_counts_.Get(s_reg) + weight);
}
if (!(cu_->disable_opt & (1 << kPromoteCompilerTemps))) {
- int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+ uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
// Implicit use of Method* ? */
if (df_attributes & DF_UMS) {
/*
* Some invokes will not use Method* - need to perform test similar
* to that found in GenInvoke() to decide whether to count refs
- * for Method* on invoke-class opcodes.
- * TODO: refactor for common test here, save results for GenInvoke
+ * for Method* on invoke-class opcodes. This is a relatively expensive
+ * operation, so should only be done once.
+ * TODO: refactor InvokeUsesMethodStar() to perform check at parse time,
+ * and save results for both here and GenInvoke. For now, go ahead
+ * and assume all invokes use method*.
*/
- int uses_method_star = true;
- if ((df_attributes & (DF_FORMAT_35C | DF_FORMAT_3RC)) &&
- !(df_attributes & DF_NON_NULL_RET)) {
- uses_method_star &= InvokeUsesMethodStar(mir);
- }
- if (uses_method_star) {
- raw_use_counts_.Increment(method_sreg_);
- use_counts_.Put(method_sreg_, use_counts_.Get(method_sreg_) + weight);
- }
+ raw_use_counts_.Increment(method_sreg_);
+ use_counts_.Put(method_sreg_, use_counts_.Get(method_sreg_) + weight);
}
}
}
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index deaf2ffe80..2a18280133 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -650,12 +650,16 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_
int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode);
- int df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode];
+ uint64_t df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode];
if (df_flags & DF_HAS_DEFS) {
def_count_ += (df_flags & DF_A_WIDE) ? 2 : 1;
}
+ if (df_flags & DF_LVN) {
+ cur_block->use_lvn = true; // Run local value numbering on this basic block.
+ }
+
// Check for inline data block signatures
if (opcode == Instruction::NOP) {
// A simple NOP will have a width of 1 at this point, embedded data NOP > 1.
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 8c20728a51..bffec394d6 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -92,41 +92,43 @@ enum DataFlowAttributePos {
kRefB,
kRefC,
kUsesMethodStar, // Implicit use of Method*.
+ kDoLVN, // Worth computing local value numbers.
};
-#define DF_NOP 0
-#define DF_UA (1 << kUA)
-#define DF_UB (1 << kUB)
-#define DF_UC (1 << kUC)
-#define DF_A_WIDE (1 << kAWide)
-#define DF_B_WIDE (1 << kBWide)
-#define DF_C_WIDE (1 << kCWide)
-#define DF_DA (1 << kDA)
-#define DF_IS_MOVE (1 << kIsMove)
-#define DF_SETS_CONST (1 << kSetsConst)
-#define DF_FORMAT_35C (1 << kFormat35c)
-#define DF_FORMAT_3RC (1 << kFormat3rc)
-#define DF_NULL_CHK_0 (1 << kNullCheckSrc0)
-#define DF_NULL_CHK_1 (1 << kNullCheckSrc1)
-#define DF_NULL_CHK_2 (1 << kNullCheckSrc2)
-#define DF_NULL_CHK_OUT0 (1 << kNullCheckOut0)
-#define DF_NON_NULL_DST (1 << kDstNonNull)
-#define DF_NON_NULL_RET (1 << kRetNonNull)
-#define DF_NULL_TRANSFER_0 (1 << kNullTransferSrc0)
-#define DF_NULL_TRANSFER_N (1 << kNullTransferSrcN)
-#define DF_RANGE_CHK_1 (1 << kRangeCheckSrc1)
-#define DF_RANGE_CHK_2 (1 << kRangeCheckSrc2)
-#define DF_RANGE_CHK_3 (1 << kRangeCheckSrc3)
-#define DF_FP_A (1 << kFPA)
-#define DF_FP_B (1 << kFPB)
-#define DF_FP_C (1 << kFPC)
-#define DF_CORE_A (1 << kCoreA)
-#define DF_CORE_B (1 << kCoreB)
-#define DF_CORE_C (1 << kCoreC)
-#define DF_REF_A (1 << kRefA)
-#define DF_REF_B (1 << kRefB)
-#define DF_REF_C (1 << kRefC)
-#define DF_UMS (1 << kUsesMethodStar)
+#define DF_NOP 0ULL
+#define DF_UA (1ULL << kUA)
+#define DF_UB (1ULL << kUB)
+#define DF_UC (1ULL << kUC)
+#define DF_A_WIDE (1ULL << kAWide)
+#define DF_B_WIDE (1ULL << kBWide)
+#define DF_C_WIDE (1ULL << kCWide)
+#define DF_DA (1ULL << kDA)
+#define DF_IS_MOVE (1ULL << kIsMove)
+#define DF_SETS_CONST (1ULL << kSetsConst)
+#define DF_FORMAT_35C (1ULL << kFormat35c)
+#define DF_FORMAT_3RC (1ULL << kFormat3rc)
+#define DF_NULL_CHK_0 (1ULL << kNullCheckSrc0)
+#define DF_NULL_CHK_1 (1ULL << kNullCheckSrc1)
+#define DF_NULL_CHK_2 (1ULL << kNullCheckSrc2)
+#define DF_NULL_CHK_OUT0 (1ULL << kNullCheckOut0)
+#define DF_NON_NULL_DST (1ULL << kDstNonNull)
+#define DF_NON_NULL_RET (1ULL << kRetNonNull)
+#define DF_NULL_TRANSFER_0 (1ULL << kNullTransferSrc0)
+#define DF_NULL_TRANSFER_N (1ULL << kNullTransferSrcN)
+#define DF_RANGE_CHK_1 (1ULL << kRangeCheckSrc1)
+#define DF_RANGE_CHK_2 (1ULL << kRangeCheckSrc2)
+#define DF_RANGE_CHK_3 (1ULL << kRangeCheckSrc3)
+#define DF_FP_A (1ULL << kFPA)
+#define DF_FP_B (1ULL << kFPB)
+#define DF_FP_C (1ULL << kFPC)
+#define DF_CORE_A (1ULL << kCoreA)
+#define DF_CORE_B (1ULL << kCoreB)
+#define DF_CORE_C (1ULL << kCoreC)
+#define DF_REF_A (1ULL << kRefA)
+#define DF_REF_B (1ULL << kRefB)
+#define DF_REF_C (1ULL << kRefC)
+#define DF_UMS (1ULL << kUsesMethodStar)
+#define DF_LVN (1ULL << kDoLVN)
#define DF_HAS_USES (DF_UA | DF_UB | DF_UC)
@@ -273,8 +275,9 @@ struct BasicBlock {
bool catch_entry:1;
bool explicit_throw:1;
bool conditional_branch:1;
- bool terminated_by_return:1; // Block ends with a Dalvik return opcode.
- bool dominates_return:1; // Is a member of return extended basic block.
+ bool terminated_by_return:1; // Block ends with a Dalvik return opcode.
+ bool dominates_return:1; // Is a member of return extended basic block.
+ bool use_lvn:1; // Run local value numbering on this block.
MIR* first_mir_insn;
MIR* last_mir_insn;
BasicBlockDataFlow* data_flow_info;
@@ -451,7 +454,9 @@ class MIRGraph {
void DumpCFG(const char* dir_prefix, bool all_blocks);
- void BuildRegLocations();
+ void InitRegLocations();
+
+ void RemapRegLocations();
void DumpRegLocTable(RegLocation* table, int count);
@@ -619,7 +624,7 @@ class MIRGraph {
void MethodUseCount();
void SSATransformation();
void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb);
- void NullCheckElimination();
+ void NullCheckEliminationAndTypeInference();
/*
* Type inference handling helpers. Because Dalvik's bytecode is not fully typed,
* we have to do some work to figure out the sreg type. For some operations it is
@@ -675,7 +680,7 @@ class MIRGraph {
GrowableArray<CompilerTemp*> compiler_temps_;
SafeMap<unsigned int, unsigned int> block_id_map_; // Block collapse lookup cache.
- static const int oat_data_flow_attributes_[kMirOpLast];
+ static const uint64_t oat_data_flow_attributes_[kMirOpLast];
static const char* extended_mir_op_names_[kMirOpLast - kMirOpFirst];
static const uint32_t analysis_attributes_[kMirOpLast];
@@ -711,7 +716,7 @@ class MIRGraph {
bool FindLocalLiveIn(BasicBlock* bb);
void ClearAllVisitedFlags();
bool CountUses(struct BasicBlock* bb);
- bool InferTypeAndSize(BasicBlock* bb);
+ bool InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed);
bool VerifyPredInfo(BasicBlock* bb);
BasicBlock* NeedsVisit(BasicBlock* bb);
BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb);
@@ -727,7 +732,7 @@ class MIRGraph {
void SetConstantWide(int ssa_reg, int64_t value);
int GetSSAUseCount(int s_reg);
bool BasicBlockOpt(BasicBlock* bb);
- bool EliminateNullChecks(BasicBlock* bb);
+ bool EliminateNullChecksAndInferTypes(BasicBlock* bb);
void NullCheckEliminationInit(BasicBlock* bb);
bool BuildExtendedBBList(struct BasicBlock* bb);
bool FillDefBlockMatrix(BasicBlock* bb);
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index f5913a5ad4..635393796a 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -40,7 +40,7 @@ void MIRGraph::DoConstantPropogation(BasicBlock* bb) {
MIR* mir;
for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
- int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+ uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
DecodedInstruction *d_insn = &mir->dalvikInsn;
@@ -155,7 +155,7 @@ BasicBlock* MIRGraph::NextDominatedBlock(BasicBlock* bb) {
|| (bb->block_type == kExitBlock));
BasicBlock* bb_taken = GetBasicBlock(bb->taken);
BasicBlock* bb_fall_through = GetBasicBlock(bb->fall_through);
- if (((bb_taken != NULL) && (bb_fall_through == NULL)) &&
+ if (((bb_fall_through == NULL) && (bb_taken != NULL)) &&
((bb_taken->block_type == kDalvikByteCode) || (bb_taken->block_type == kExitBlock))) {
// Follow simple unconditional branches.
bb = bb_taken;
@@ -216,11 +216,17 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) {
return true;
}
int num_temps = 0;
- LocalValueNumbering local_valnum(cu_);
+ bool use_lvn = bb->use_lvn;
+ UniquePtr<LocalValueNumbering> local_valnum;
+ if (use_lvn) {
+ local_valnum.reset(new LocalValueNumbering(cu_));
+ }
while (bb != NULL) {
for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
// TUNING: use the returned value number for CSE.
- local_valnum.GetValueNumber(mir);
+ if (use_lvn) {
+ local_valnum->GetValueNumber(mir);
+ }
// Look for interesting opcodes, skip otherwise
Instruction::Code opcode = mir->dalvikInsn.opcode;
switch (opcode) {
@@ -463,7 +469,7 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) {
}
}
}
- bb = NextDominatedBlock(bb);
+ bb = ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) ? NextDominatedBlock(bb) : NULL;
}
if (num_temps > cu_->num_compiler_temps) {
@@ -486,7 +492,7 @@ void MIRGraph::CountChecks(struct BasicBlock* bb) {
if (mir->ssa_rep == NULL) {
continue;
}
- int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+ uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
if (df_attributes & DF_HAS_NULL_CHKS) {
checkstats_->null_checks++;
if (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) {
@@ -571,7 +577,7 @@ bool MIRGraph::CombineBlocks(struct BasicBlock* bb) {
MIR* mir = bb->last_mir_insn;
// Grab the attributes from the paired opcode
MIR* throw_insn = mir->meta.throw_insn;
- int df_attributes = oat_data_flow_attributes_[throw_insn->dalvikInsn.opcode];
+ uint64_t df_attributes = oat_data_flow_attributes_[throw_insn->dalvikInsn.opcode];
bool can_combine = true;
if (df_attributes & DF_HAS_NULL_CHKS) {
can_combine &= ((throw_insn->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0);
@@ -618,74 +624,87 @@ bool MIRGraph::CombineBlocks(struct BasicBlock* bb) {
return false;
}
-/* Eliminate unnecessary null checks for a basic block. */
-bool MIRGraph::EliminateNullChecks(struct BasicBlock* bb) {
+/*
+ * Eliminate unnecessary null checks for a basic block. Also, while we're doing
+ * an iterative walk go ahead and perform type and size inference.
+ */
+bool MIRGraph::EliminateNullChecksAndInferTypes(struct BasicBlock* bb) {
if (bb->data_flow_info == NULL) return false;
+ bool infer_changed = false;
+ bool do_nce = ((cu_->disable_opt & (1 << kNullCheckElimination)) == 0);
- /*
- * Set initial state. Be conservative with catch
- * blocks and start with no assumptions about null check
- * status (except for "this").
- */
- if ((bb->block_type == kEntryBlock) | bb->catch_entry) {
- temp_ssa_register_v_->ClearAllBits();
- // Assume all ins are objects.
- for (uint16_t in_reg = cu_->num_dalvik_registers - cu_->num_ins;
- in_reg < cu_->num_dalvik_registers; in_reg++) {
- temp_ssa_register_v_->SetBit(in_reg);
- }
- if ((cu_->access_flags & kAccStatic) == 0) {
- // If non-static method, mark "this" as non-null
- int this_reg = cu_->num_dalvik_registers - cu_->num_ins;
- temp_ssa_register_v_->ClearBit(this_reg);
- }
- } else if (bb->predecessors->Size() == 1) {
- BasicBlock* pred_bb = GetBasicBlock(bb->predecessors->Get(0));
- temp_ssa_register_v_->Copy(pred_bb->data_flow_info->ending_null_check_v);
- if (pred_bb->block_type == kDalvikByteCode) {
- // Check to see if predecessor had an explicit null-check.
- MIR* last_insn = pred_bb->last_mir_insn;
- Instruction::Code last_opcode = last_insn->dalvikInsn.opcode;
- if (last_opcode == Instruction::IF_EQZ) {
- if (pred_bb->fall_through == bb->id) {
- // The fall-through of a block following a IF_EQZ, set the vA of the IF_EQZ to show that
- // it can't be null.
- temp_ssa_register_v_->ClearBit(last_insn->ssa_rep->uses[0]);
- }
- } else if (last_opcode == Instruction::IF_NEZ) {
- if (pred_bb->taken == bb->id) {
- // The taken block following a IF_NEZ, set the vA of the IF_NEZ to show that it can't be
- // null.
- temp_ssa_register_v_->ClearBit(last_insn->ssa_rep->uses[0]);
+ if (do_nce) {
+ /*
+ * Set initial state. Be conservative with catch
+ * blocks and start with no assumptions about null check
+ * status (except for "this").
+ */
+ if ((bb->block_type == kEntryBlock) | bb->catch_entry) {
+ temp_ssa_register_v_->ClearAllBits();
+ // Assume all ins are objects.
+ for (uint16_t in_reg = cu_->num_dalvik_registers - cu_->num_ins;
+ in_reg < cu_->num_dalvik_registers; in_reg++) {
+ temp_ssa_register_v_->SetBit(in_reg);
+ }
+ if ((cu_->access_flags & kAccStatic) == 0) {
+ // If non-static method, mark "this" as non-null
+ int this_reg = cu_->num_dalvik_registers - cu_->num_ins;
+ temp_ssa_register_v_->ClearBit(this_reg);
+ }
+ } else if (bb->predecessors->Size() == 1) {
+ BasicBlock* pred_bb = GetBasicBlock(bb->predecessors->Get(0));
+ temp_ssa_register_v_->Copy(pred_bb->data_flow_info->ending_null_check_v);
+ if (pred_bb->block_type == kDalvikByteCode) {
+ // Check to see if predecessor had an explicit null-check.
+ MIR* last_insn = pred_bb->last_mir_insn;
+ Instruction::Code last_opcode = last_insn->dalvikInsn.opcode;
+ if (last_opcode == Instruction::IF_EQZ) {
+ if (pred_bb->fall_through == bb->id) {
+ // The fall-through of a block following a IF_EQZ, set the vA of the IF_EQZ to show that
+ // it can't be null.
+ temp_ssa_register_v_->ClearBit(last_insn->ssa_rep->uses[0]);
+ }
+ } else if (last_opcode == Instruction::IF_NEZ) {
+ if (pred_bb->taken == bb->id) {
+ // The taken block following a IF_NEZ, set the vA of the IF_NEZ to show that it can't be
+ // null.
+ temp_ssa_register_v_->ClearBit(last_insn->ssa_rep->uses[0]);
+ }
}
}
- }
- } else {
- // Starting state is union of all incoming arcs
- GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors);
- BasicBlock* pred_bb = GetBasicBlock(iter.Next());
- DCHECK(pred_bb != NULL);
- temp_ssa_register_v_->Copy(pred_bb->data_flow_info->ending_null_check_v);
- while (true) {
- pred_bb = GetBasicBlock(iter.Next());
- if (!pred_bb) break;
- if ((pred_bb->data_flow_info == NULL) ||
- (pred_bb->data_flow_info->ending_null_check_v == NULL)) {
- continue;
+ } else {
+ // Starting state is union of all incoming arcs
+ GrowableArray<BasicBlockId>::Iterator iter(bb->predecessors);
+ BasicBlock* pred_bb = GetBasicBlock(iter.Next());
+ DCHECK(pred_bb != NULL);
+ temp_ssa_register_v_->Copy(pred_bb->data_flow_info->ending_null_check_v);
+ while (true) {
+ pred_bb = GetBasicBlock(iter.Next());
+ if (!pred_bb) break;
+ if ((pred_bb->data_flow_info == NULL) ||
+ (pred_bb->data_flow_info->ending_null_check_v == NULL)) {
+ continue;
+ }
+ temp_ssa_register_v_->Union(pred_bb->data_flow_info->ending_null_check_v);
}
- temp_ssa_register_v_->Union(pred_bb->data_flow_info->ending_null_check_v);
}
+ // At this point, temp_ssa_register_v_ shows which sregs have an object definition with
+ // no intervening uses.
}
- // At this point, temp_ssa_register_v_ shows which sregs have an object definition with
- // no intervening uses.
-
// Walk through the instruction in the block, updating as necessary
for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
if (mir->ssa_rep == NULL) {
continue;
}
- int df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+
+ // Propagate type info.
+ infer_changed = InferTypeAndSize(bb, mir, infer_changed);
+ if (!do_nce) {
+ continue;
+ }
+
+ uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
// Might need a null check?
if (df_attributes & DF_HAS_NULL_CHKS) {
@@ -784,25 +803,25 @@ bool MIRGraph::EliminateNullChecks(struct BasicBlock* bb) {
}
// Did anything change?
- bool changed = !temp_ssa_register_v_->Equal(bb->data_flow_info->ending_null_check_v);
- if (changed) {
+ bool nce_changed = do_nce && !temp_ssa_register_v_->Equal(bb->data_flow_info->ending_null_check_v);
+ if (nce_changed) {
bb->data_flow_info->ending_null_check_v->Copy(temp_ssa_register_v_);
}
- return changed;
+ return infer_changed | nce_changed;
}
-void MIRGraph::NullCheckElimination() {
- if (!(cu_->disable_opt & (1 << kNullCheckElimination))) {
- DCHECK(temp_ssa_register_v_ != NULL);
+void MIRGraph::NullCheckEliminationAndTypeInference() {
+ DCHECK(temp_ssa_register_v_ != NULL);
+ if ((cu_->disable_opt & (1 << kNullCheckElimination)) == 0) {
AllNodesIterator iter(this);
for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
NullCheckEliminationInit(bb);
}
- RepeatingPreOrderDfsIterator iter2(this);
- bool change = false;
- for (BasicBlock* bb = iter2.Next(change); bb != NULL; bb = iter2.Next(change)) {
- change = EliminateNullChecks(bb);
- }
+ }
+ RepeatingPreOrderDfsIterator iter2(this);
+ bool change = false;
+ for (BasicBlock* bb = iter2.Next(change); bb != NULL; bb = iter2.Next(change)) {
+ change = EliminateNullChecksAndInferTypes(bb);
}
if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
DumpCFG("/sdcard/4_post_nce_cfg/", false);
@@ -810,12 +829,14 @@ void MIRGraph::NullCheckElimination() {
}
void MIRGraph::BasicBlockCombine() {
- PreOrderDfsIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
- CombineBlocks(bb);
- }
- if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
- DumpCFG("/sdcard/5_post_bbcombine_cfg/", false);
+ if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
+ PreOrderDfsIterator iter(this);
+ for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
+ CombineBlocks(bb);
+ }
+ if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
+ DumpCFG("/sdcard/5_post_bbcombine_cfg/", false);
+ }
}
}
@@ -868,17 +889,20 @@ bool MIRGraph::BuildExtendedBBList(struct BasicBlock* bb) {
BasicBlock* start_bb = bb;
extended_basic_blocks_.push_back(bb->id);
bool terminated_by_return = false;
+ bool do_local_value_numbering = false;
// Visit blocks strictly dominated by this head.
while (bb != NULL) {
bb->visited = true;
terminated_by_return |= bb->terminated_by_return;
+ do_local_value_numbering |= bb->use_lvn;
bb = NextDominatedBlock(bb);
}
- if (terminated_by_return) {
- // This extended basic block contains a return, so mark all members.
+ if (terminated_by_return || do_local_value_numbering) {
+ // Do lvn for all blocks in this extended set.
bb = start_bb;
while (bb != NULL) {
- bb->dominates_return = true;
+ bb->use_lvn = do_local_value_numbering;
+ bb->dominates_return = terminated_by_return;
bb = NextDominatedBlock(bb);
}
}
@@ -889,14 +913,21 @@ bool MIRGraph::BuildExtendedBBList(struct BasicBlock* bb) {
void MIRGraph::BasicBlockOptimization() {
if (!(cu_->disable_opt & (1 << kBBOpt))) {
DCHECK_EQ(cu_->num_compiler_temps, 0);
- ClearAllVisitedFlags();
- PreOrderDfsIterator iter2(this);
- for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
- BuildExtendedBBList(bb);
+ if ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) {
+ ClearAllVisitedFlags();
+ PreOrderDfsIterator iter2(this);
+ for (BasicBlock* bb = iter2.Next(); bb != NULL; bb = iter2.Next()) {
+ BuildExtendedBBList(bb);
+ }
+ // Perform extended basic block optimizations.
+ for (unsigned int i = 0; i < extended_basic_blocks_.size(); i++) {
+ BasicBlockOpt(GetBasicBlock(extended_basic_blocks_[i]));
+ }
}
- // Perform extended basic block optimizations.
- for (unsigned int i = 0; i < extended_basic_blocks_.size(); i++) {
- BasicBlockOpt(GetBasicBlock(extended_basic_blocks_[i]));
+ } else {
+ PreOrderDfsIterator iter(this);
+ for (BasicBlock* bb = iter.Next(); bb != NULL; bb = iter.Next()) {
+ BasicBlockOpt(bb);
}
}
if (cu_->enable_debug & (1 << kDebugDumpCFG)) {
diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc
index 07bd2aa979..e5b4876f08 100644
--- a/compiler/dex/portable/mir_to_gbc.cc
+++ b/compiler/dex/portable/mir_to_gbc.cc
@@ -705,7 +705,7 @@ bool MirConverter::ConvertMIRNode(MIR* mir, BasicBlock* bb,
/* Prep Src and Dest locations */
int next_sreg = 0;
int next_loc = 0;
- int attrs = mir_graph_->oat_data_flow_attributes_[opcode];
+ uint64_t attrs = mir_graph_->oat_data_flow_attributes_[opcode];
rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
if (attrs & DF_UA) {
if (attrs & DF_A_WIDE) {
diff --git a/compiler/dex/quick/arm/assemble_arm.cc b/compiler/dex/quick/arm/assemble_arm.cc
index b3236ae23e..820b3aa24e 100644
--- a/compiler/dex/quick/arm/assemble_arm.cc
+++ b/compiler/dex/quick/arm/assemble_arm.cc
@@ -1615,7 +1615,6 @@ void ArmMir2Lir::AssembleLIR() {
data_offset_ = (code_buffer_.size() + 0x3) & ~0x3;
- cu_->NewTimingSplit("LiteralData");
// Install literals
InstallLiteralPools();
diff --git a/compiler/dex/quick/local_optimizations.cc b/compiler/dex/quick/local_optimizations.cc
index 0f29578c4e..7a2dce13dc 100644
--- a/compiler/dex/quick/local_optimizations.cc
+++ b/compiler/dex/quick/local_optimizations.cc
@@ -291,9 +291,9 @@ void Mir2Lir::ApplyLoadHoisting(LIR* head_lir, LIR* tail_lir) {
uint64_t target_flags = GetTargetInstFlags(this_lir->opcode);
/* Skip non-interesting instructions */
- if ((this_lir->flags.is_nop == true) ||
- ((target_flags & (REG_DEF0 | REG_DEF1)) == (REG_DEF0 | REG_DEF1)) ||
- !(target_flags & IS_LOAD)) {
+ if (!(target_flags & IS_LOAD) ||
+ (this_lir->flags.is_nop == true) ||
+ ((target_flags & (REG_DEF0 | REG_DEF1)) == (REG_DEF0 | REG_DEF1))) {
continue;
}
diff --git a/compiler/dex/quick/mips/assemble_mips.cc b/compiler/dex/quick/mips/assemble_mips.cc
index 5f5e5e44ac..bd3355f8da 100644
--- a/compiler/dex/quick/mips/assemble_mips.cc
+++ b/compiler/dex/quick/mips/assemble_mips.cc
@@ -793,7 +793,6 @@ void MipsMir2Lir::AssembleLIR() {
}
// Install literals
- cu_->NewTimingSplit("LiteralData");
InstallLiteralPools();
// Install switch tables
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index fa9a3ad566..19d04be6df 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -39,7 +39,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list
// Prep Src and Dest locations.
int next_sreg = 0;
int next_loc = 0;
- int attrs = mir_graph_->oat_data_flow_attributes_[opcode];
+ uint64_t attrs = mir_graph_->oat_data_flow_attributes_[opcode];
rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc();
if (attrs & DF_UA) {
if (attrs & DF_A_WIDE) {
diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc
index 2047f30765..191c9c701b 100644
--- a/compiler/dex/quick/x86/assemble_x86.cc
+++ b/compiler/dex/quick/x86/assemble_x86.cc
@@ -1503,7 +1503,6 @@ void X86Mir2Lir::AssembleLIR() {
}
}
- cu_->NewTimingSplit("LiteralData");
// Install literals
InstallLiteralPools();
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index 32fac0b393..bef966c8ff 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -121,260 +121,251 @@ bool MIRGraph::SetHigh(int index) {
* as it doesn't propagate. We're guaranteed at least one pass through
* the cfg.
*/
-bool MIRGraph::InferTypeAndSize(BasicBlock* bb) {
- MIR *mir;
- bool changed = false; // Did anything change?
-
- if (bb->data_flow_info == NULL) return false;
- if (bb->block_type != kDalvikByteCode && bb->block_type != kEntryBlock)
- return false;
-
- for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
- SSARepresentation *ssa_rep = mir->ssa_rep;
- if (ssa_rep) {
- int attrs = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
- const int* uses = ssa_rep->uses;
- const int* defs = ssa_rep->defs;
+bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) {
+ SSARepresentation *ssa_rep = mir->ssa_rep;
+ if (ssa_rep) {
+ uint64_t attrs = oat_data_flow_attributes_[mir->dalvikInsn.opcode];
+ const int* uses = ssa_rep->uses;
+ const int* defs = ssa_rep->defs;
+
+ // Handle defs
+ if (attrs & DF_DA) {
+ if (attrs & DF_CORE_A) {
+ changed |= SetCore(defs[0]);
+ }
+ if (attrs & DF_REF_A) {
+ changed |= SetRef(defs[0]);
+ }
+ if (attrs & DF_A_WIDE) {
+ reg_location_[defs[0]].wide = true;
+ reg_location_[defs[1]].wide = true;
+ reg_location_[defs[1]].high_word = true;
+ DCHECK_EQ(SRegToVReg(defs[0])+1,
+ SRegToVReg(defs[1]));
+ }
+ }
- // Handle defs
- if (attrs & DF_DA) {
- if (attrs & DF_CORE_A) {
- changed |= SetCore(defs[0]);
- }
- if (attrs & DF_REF_A) {
- changed |= SetRef(defs[0]);
- }
- if (attrs & DF_A_WIDE) {
- reg_location_[defs[0]].wide = true;
- reg_location_[defs[1]].wide = true;
- reg_location_[defs[1]].high_word = true;
- DCHECK_EQ(SRegToVReg(defs[0])+1,
- SRegToVReg(defs[1]));
- }
+ // Handles uses
+ int next = 0;
+ if (attrs & DF_UA) {
+ if (attrs & DF_CORE_A) {
+ changed |= SetCore(uses[next]);
+ }
+ if (attrs & DF_REF_A) {
+ changed |= SetRef(uses[next]);
+ }
+ if (attrs & DF_A_WIDE) {
+ reg_location_[uses[next]].wide = true;
+ reg_location_[uses[next + 1]].wide = true;
+ reg_location_[uses[next + 1]].high_word = true;
+ DCHECK_EQ(SRegToVReg(uses[next])+1,
+ SRegToVReg(uses[next + 1]));
+ next += 2;
+ } else {
+ next++;
+ }
+ }
+ if (attrs & DF_UB) {
+ if (attrs & DF_CORE_B) {
+ changed |= SetCore(uses[next]);
+ }
+ if (attrs & DF_REF_B) {
+ changed |= SetRef(uses[next]);
+ }
+ if (attrs & DF_B_WIDE) {
+ reg_location_[uses[next]].wide = true;
+ reg_location_[uses[next + 1]].wide = true;
+ reg_location_[uses[next + 1]].high_word = true;
+ DCHECK_EQ(SRegToVReg(uses[next])+1,
+ SRegToVReg(uses[next + 1]));
+ next += 2;
+ } else {
+ next++;
+ }
+ }
+ if (attrs & DF_UC) {
+ if (attrs & DF_CORE_C) {
+ changed |= SetCore(uses[next]);
+ }
+ if (attrs & DF_REF_C) {
+ changed |= SetRef(uses[next]);
}
+ if (attrs & DF_C_WIDE) {
+ reg_location_[uses[next]].wide = true;
+ reg_location_[uses[next + 1]].wide = true;
+ reg_location_[uses[next + 1]].high_word = true;
+ DCHECK_EQ(SRegToVReg(uses[next])+1,
+ SRegToVReg(uses[next + 1]));
+ }
+ }
- // Handles uses
- int next = 0;
- if (attrs & DF_UA) {
- if (attrs & DF_CORE_A) {
- changed |= SetCore(uses[next]);
- }
- if (attrs & DF_REF_A) {
- changed |= SetRef(uses[next]);
- }
- if (attrs & DF_A_WIDE) {
- reg_location_[uses[next]].wide = true;
- reg_location_[uses[next + 1]].wide = true;
- reg_location_[uses[next + 1]].high_word = true;
- DCHECK_EQ(SRegToVReg(uses[next])+1,
- SRegToVReg(uses[next + 1]));
- next += 2;
- } else {
- next++;
- }
+ // Special-case return handling
+ if ((mir->dalvikInsn.opcode == Instruction::RETURN) ||
+ (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) ||
+ (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
+ switch (cu_->shorty[0]) {
+ case 'I':
+ changed |= SetCore(uses[0]);
+ break;
+ case 'J':
+ changed |= SetCore(uses[0]);
+ changed |= SetCore(uses[1]);
+ reg_location_[uses[0]].wide = true;
+ reg_location_[uses[1]].wide = true;
+ reg_location_[uses[1]].high_word = true;
+ break;
+ case 'F':
+ changed |= SetFp(uses[0]);
+ break;
+ case 'D':
+ changed |= SetFp(uses[0]);
+ changed |= SetFp(uses[1]);
+ reg_location_[uses[0]].wide = true;
+ reg_location_[uses[1]].wide = true;
+ reg_location_[uses[1]].high_word = true;
+ break;
+ case 'L':
+ changed |= SetRef(uses[0]);
+ break;
+ default: break;
}
- if (attrs & DF_UB) {
- if (attrs & DF_CORE_B) {
- changed |= SetCore(uses[next]);
- }
- if (attrs & DF_REF_B) {
- changed |= SetRef(uses[next]);
- }
- if (attrs & DF_B_WIDE) {
- reg_location_[uses[next]].wide = true;
- reg_location_[uses[next + 1]].wide = true;
- reg_location_[uses[next + 1]].high_word = true;
- DCHECK_EQ(SRegToVReg(uses[next])+1,
- SRegToVReg(uses[next + 1]));
- next += 2;
- } else {
- next++;
+ }
+
+ // Special-case handling for format 35c/3rc invokes
+ Instruction::Code opcode = mir->dalvikInsn.opcode;
+ int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
+ ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
+ if ((flags & Instruction::kInvoke) &&
+ (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
+ DCHECK_EQ(next, 0);
+ int target_idx = mir->dalvikInsn.vB;
+ const char* shorty = GetShortyFromTargetIdx(target_idx);
+ // Handle result type if floating point
+ if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
+ MIR* move_result_mir = FindMoveResult(bb, mir);
+ // Result might not be used at all, so no move-result
+ if (move_result_mir && (move_result_mir->dalvikInsn.opcode !=
+ Instruction::MOVE_RESULT_OBJECT)) {
+ SSARepresentation* tgt_rep = move_result_mir->ssa_rep;
+ DCHECK(tgt_rep != NULL);
+ tgt_rep->fp_def[0] = true;
+ changed |= SetFp(tgt_rep->defs[0]);
+ if (shorty[0] == 'D') {
+ tgt_rep->fp_def[1] = true;
+ changed |= SetFp(tgt_rep->defs[1]);
+ }
}
}
- if (attrs & DF_UC) {
- if (attrs & DF_CORE_C) {
- changed |= SetCore(uses[next]);
- }
- if (attrs & DF_REF_C) {
- changed |= SetRef(uses[next]);
- }
- if (attrs & DF_C_WIDE) {
- reg_location_[uses[next]].wide = true;
- reg_location_[uses[next + 1]].wide = true;
- reg_location_[uses[next + 1]].high_word = true;
- DCHECK_EQ(SRegToVReg(uses[next])+1,
- SRegToVReg(uses[next + 1]));
- }
+ int num_uses = mir->dalvikInsn.vA;
+ // If this is a non-static invoke, mark implicit "this"
+ if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
+ (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
+ reg_location_[uses[next]].defined = true;
+ reg_location_[uses[next]].ref = true;
+ next++;
}
-
- // Special-case return handling
- if ((mir->dalvikInsn.opcode == Instruction::RETURN) ||
- (mir->dalvikInsn.opcode == Instruction::RETURN_WIDE) ||
- (mir->dalvikInsn.opcode == Instruction::RETURN_OBJECT)) {
- switch (cu_->shorty[0]) {
- case 'I':
- changed |= SetCore(uses[0]);
+ uint32_t cpos = 1;
+ if (strlen(shorty) > 1) {
+ for (int i = next; i < num_uses;) {
+ DCHECK_LT(cpos, strlen(shorty));
+ switch (shorty[cpos++]) {
+ case 'D':
+ ssa_rep->fp_use[i] = true;
+ ssa_rep->fp_use[i+1] = true;
+ reg_location_[uses[i]].wide = true;
+ reg_location_[uses[i+1]].wide = true;
+ reg_location_[uses[i+1]].high_word = true;
+ DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1]));
+ i++;
break;
case 'J':
- changed |= SetCore(uses[0]);
- changed |= SetCore(uses[1]);
- reg_location_[uses[0]].wide = true;
- reg_location_[uses[1]].wide = true;
- reg_location_[uses[1]].high_word = true;
+ reg_location_[uses[i]].wide = true;
+ reg_location_[uses[i+1]].wide = true;
+ reg_location_[uses[i+1]].high_word = true;
+ DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1]));
+ changed |= SetCore(uses[i]);
+ i++;
break;
case 'F':
- changed |= SetFp(uses[0]);
- break;
- case 'D':
- changed |= SetFp(uses[0]);
- changed |= SetFp(uses[1]);
- reg_location_[uses[0]].wide = true;
- reg_location_[uses[1]].wide = true;
- reg_location_[uses[1]].high_word = true;
+ ssa_rep->fp_use[i] = true;
break;
case 'L':
- changed |= SetRef(uses[0]);
+ changed |= SetRef(uses[i]);
+ break;
+ default:
+ changed |= SetCore(uses[i]);
break;
- default: break;
- }
- }
-
- // Special-case handling for format 35c/3rc invokes
- Instruction::Code opcode = mir->dalvikInsn.opcode;
- int flags = (static_cast<int>(opcode) >= kNumPackedOpcodes)
- ? 0 : Instruction::FlagsOf(mir->dalvikInsn.opcode);
- if ((flags & Instruction::kInvoke) &&
- (attrs & (DF_FORMAT_35C | DF_FORMAT_3RC))) {
- DCHECK_EQ(next, 0);
- int target_idx = mir->dalvikInsn.vB;
- const char* shorty = GetShortyFromTargetIdx(target_idx);
- // Handle result type if floating point
- if ((shorty[0] == 'F') || (shorty[0] == 'D')) {
- MIR* move_result_mir = FindMoveResult(bb, mir);
- // Result might not be used at all, so no move-result
- if (move_result_mir && (move_result_mir->dalvikInsn.opcode !=
- Instruction::MOVE_RESULT_OBJECT)) {
- SSARepresentation* tgt_rep = move_result_mir->ssa_rep;
- DCHECK(tgt_rep != NULL);
- tgt_rep->fp_def[0] = true;
- changed |= SetFp(tgt_rep->defs[0]);
- if (shorty[0] == 'D') {
- tgt_rep->fp_def[1] = true;
- changed |= SetFp(tgt_rep->defs[1]);
- }
- }
- }
- int num_uses = mir->dalvikInsn.vA;
- // If this is a non-static invoke, mark implicit "this"
- if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
- (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
- reg_location_[uses[next]].defined = true;
- reg_location_[uses[next]].ref = true;
- next++;
- }
- uint32_t cpos = 1;
- if (strlen(shorty) > 1) {
- for (int i = next; i < num_uses;) {
- DCHECK_LT(cpos, strlen(shorty));
- switch (shorty[cpos++]) {
- case 'D':
- ssa_rep->fp_use[i] = true;
- ssa_rep->fp_use[i+1] = true;
- reg_location_[uses[i]].wide = true;
- reg_location_[uses[i+1]].wide = true;
- reg_location_[uses[i+1]].high_word = true;
- DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1]));
- i++;
- break;
- case 'J':
- reg_location_[uses[i]].wide = true;
- reg_location_[uses[i+1]].wide = true;
- reg_location_[uses[i+1]].high_word = true;
- DCHECK_EQ(SRegToVReg(uses[i])+1, SRegToVReg(uses[i+1]));
- changed |= SetCore(uses[i]);
- i++;
- break;
- case 'F':
- ssa_rep->fp_use[i] = true;
- break;
- case 'L':
- changed |= SetRef(uses[i]);
- break;
- default:
- changed |= SetCore(uses[i]);
- break;
- }
- i++;
}
+ i++;
}
}
+ }
- for (int i = 0; ssa_rep->fp_use && i< ssa_rep->num_uses; i++) {
- if (ssa_rep->fp_use[i])
- changed |= SetFp(uses[i]);
- }
- for (int i = 0; ssa_rep->fp_def && i< ssa_rep->num_defs; i++) {
- if (ssa_rep->fp_def[i])
- changed |= SetFp(defs[i]);
- }
- // Special-case handling for moves & Phi
- if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
- /*
- * If any of our inputs or outputs is defined, set all.
- * Some ugliness related to Phi nodes and wide values.
- * The Phi set will include all low words or all high
- * words, so we have to treat them specially.
- */
- bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) ==
- kMirOpPhi);
- RegLocation rl_temp = reg_location_[defs[0]];
- bool defined_fp = rl_temp.defined && rl_temp.fp;
- bool defined_core = rl_temp.defined && rl_temp.core;
- bool defined_ref = rl_temp.defined && rl_temp.ref;
- bool is_wide = rl_temp.wide || ((attrs & DF_A_WIDE) != 0);
- bool is_high = is_phi && rl_temp.wide && rl_temp.high_word;
- for (int i = 0; i < ssa_rep->num_uses; i++) {
- rl_temp = reg_location_[uses[i]];
- defined_fp |= rl_temp.defined && rl_temp.fp;
- defined_core |= rl_temp.defined && rl_temp.core;
- defined_ref |= rl_temp.defined && rl_temp.ref;
- is_wide |= rl_temp.wide;
- is_high |= is_phi && rl_temp.wide && rl_temp.high_word;
- }
- /*
- * We don't normally expect to see a Dalvik register definition used both as a
- * floating point and core value, though technically it could happen with constants.
- * Until we have proper typing, detect this situation and disable register promotion
- * (which relies on the distinction between core a fp usages).
- */
- if ((defined_fp && (defined_core | defined_ref)) &&
- ((cu_->disable_opt & (1 << kPromoteRegs)) == 0)) {
- LOG(WARNING) << PrettyMethod(cu_->method_idx, *cu_->dex_file)
- << " op at block " << bb->id
- << " has both fp and core/ref uses for same def.";
- cu_->disable_opt |= (1 << kPromoteRegs);
- }
- changed |= SetFp(defs[0], defined_fp);
- changed |= SetCore(defs[0], defined_core);
- changed |= SetRef(defs[0], defined_ref);
- changed |= SetWide(defs[0], is_wide);
- changed |= SetHigh(defs[0], is_high);
- if (attrs & DF_A_WIDE) {
- changed |= SetWide(defs[1]);
- changed |= SetHigh(defs[1]);
- }
- for (int i = 0; i < ssa_rep->num_uses; i++) {
- changed |= SetFp(uses[i], defined_fp);
- changed |= SetCore(uses[i], defined_core);
- changed |= SetRef(uses[i], defined_ref);
- changed |= SetWide(uses[i], is_wide);
- changed |= SetHigh(uses[i], is_high);
- }
- if (attrs & DF_A_WIDE) {
- DCHECK_EQ(ssa_rep->num_uses, 2);
- changed |= SetWide(uses[1]);
- changed |= SetHigh(uses[1]);
- }
+ for (int i = 0; ssa_rep->fp_use && i< ssa_rep->num_uses; i++) {
+ if (ssa_rep->fp_use[i])
+ changed |= SetFp(uses[i]);
+ }
+ for (int i = 0; ssa_rep->fp_def && i< ssa_rep->num_defs; i++) {
+ if (ssa_rep->fp_def[i])
+ changed |= SetFp(defs[i]);
+ }
+ // Special-case handling for moves & Phi
+ if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
+ /*
+ * If any of our inputs or outputs is defined, set all.
+ * Some ugliness related to Phi nodes and wide values.
+ * The Phi set will include all low words or all high
+ * words, so we have to treat them specially.
+ */
+ bool is_phi = (static_cast<int>(mir->dalvikInsn.opcode) ==
+ kMirOpPhi);
+ RegLocation rl_temp = reg_location_[defs[0]];
+ bool defined_fp = rl_temp.defined && rl_temp.fp;
+ bool defined_core = rl_temp.defined && rl_temp.core;
+ bool defined_ref = rl_temp.defined && rl_temp.ref;
+ bool is_wide = rl_temp.wide || ((attrs & DF_A_WIDE) != 0);
+ bool is_high = is_phi && rl_temp.wide && rl_temp.high_word;
+ for (int i = 0; i < ssa_rep->num_uses; i++) {
+ rl_temp = reg_location_[uses[i]];
+ defined_fp |= rl_temp.defined && rl_temp.fp;
+ defined_core |= rl_temp.defined && rl_temp.core;
+ defined_ref |= rl_temp.defined && rl_temp.ref;
+ is_wide |= rl_temp.wide;
+ is_high |= is_phi && rl_temp.wide && rl_temp.high_word;
+ }
+ /*
+ * We don't normally expect to see a Dalvik register definition used both as a
+ * floating point and core value, though technically it could happen with constants.
+ * Until we have proper typing, detect this situation and disable register promotion
+ * (which relies on the distinction between core a fp usages).
+ */
+ if ((defined_fp && (defined_core | defined_ref)) &&
+ ((cu_->disable_opt & (1 << kPromoteRegs)) == 0)) {
+ LOG(WARNING) << PrettyMethod(cu_->method_idx, *cu_->dex_file)
+ << " op at block " << bb->id
+ << " has both fp and core/ref uses for same def.";
+ cu_->disable_opt |= (1 << kPromoteRegs);
+ }
+ changed |= SetFp(defs[0], defined_fp);
+ changed |= SetCore(defs[0], defined_core);
+ changed |= SetRef(defs[0], defined_ref);
+ changed |= SetWide(defs[0], is_wide);
+ changed |= SetHigh(defs[0], is_high);
+ if (attrs & DF_A_WIDE) {
+ changed |= SetWide(defs[1]);
+ changed |= SetHigh(defs[1]);
+ }
+ for (int i = 0; i < ssa_rep->num_uses; i++) {
+ changed |= SetFp(uses[i], defined_fp);
+ changed |= SetCore(uses[i], defined_core);
+ changed |= SetRef(uses[i], defined_ref);
+ changed |= SetWide(uses[i], is_wide);
+ changed |= SetHigh(uses[i], is_high);
+ }
+ if (attrs & DF_A_WIDE) {
+ DCHECK_EQ(ssa_rep->num_uses, 2);
+ changed |= SetWide(uses[1]);
+ changed |= SetHigh(uses[1]);
}
}
}
@@ -417,13 +408,7 @@ static const RegLocation fresh_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
INVALID_REG, INVALID_REG, INVALID_SREG,
INVALID_SREG};
-/*
- * Simple register allocation. Some Dalvik virtual registers may
- * be promoted to physical registers. Most of the work for temp
- * allocation is done on the fly. We also do some initialization and
- * type inference here.
- */
-void MIRGraph::BuildRegLocations() {
+void MIRGraph::InitRegLocations() {
/* Allocate the location map */
RegLocation* loc = static_cast<RegLocation*>(arena_->Alloc(GetNumSSARegs() * sizeof(*loc),
ArenaAllocator::kAllocRegAlloc));
@@ -493,19 +478,14 @@ void MIRGraph::BuildRegLocations() {
s_reg++;
}
}
+}
- /* Do type & size inference pass */
- RepeatingPreOrderDfsIterator iter(this);
- bool change = false;
- for (BasicBlock* bb = iter.Next(false); bb != NULL; bb = iter.Next(change)) {
- change = InferTypeAndSize(bb);
- }
-
- /*
- * Set the s_reg_low field to refer to the pre-SSA name of the
- * base Dalvik virtual register. Once we add a better register
- * allocator, remove this remapping.
- */
+/*
+ * Set the s_reg_low field to refer to the pre-SSA name of the
+ * base Dalvik virtual register. Once we add a better register
+ * allocator, remove this remapping.
+ */
+void MIRGraph::RemapRegLocations() {
for (int i = 0; i < GetNumSSARegs(); i++) {
if (reg_location_[i].location != kLocCompilerTemp) {
int orig_sreg = reg_location_[i].s_reg_low;