Quick: Reduce memory usage and improve compile time.
Move the def-block-matrix from Arena to ScopedArena. Remove
BasicBlockDataFlow::ending_check_v and use a temporary bit
matrix instead. Remove unused BasicBlockDataFlow::phi_v.
Avoid some BitVector::Copy() at the end of null and clinit
check elimination passes when the contents of the source
BitVector is no longer needed.
Change-Id: I8111b2f8a51e63075aa124b528d61b79b6933274
diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc
index 276b886..7e83c0c 100644
--- a/compiler/dex/mir_graph.cc
+++ b/compiler/dex/mir_graph.cc
@@ -94,11 +94,11 @@
topological_order_indexes_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
topological_order_loop_head_stack_(arena->Adapter(kArenaAllocTopologicalSortOrder)),
i_dom_list_(NULL),
- def_block_matrix_(NULL),
temp_scoped_alloc_(),
temp_insn_data_(nullptr),
temp_bit_vector_size_(0u),
temp_bit_vector_(nullptr),
+ temp_bit_matrix_(nullptr),
temp_gvn_(),
block_list_(arena->Adapter(kArenaAllocBBList)),
try_block_addr_(NULL),
@@ -1706,6 +1706,7 @@
temp_bit_vector_size_ = 0u;
temp_bit_vector_ = nullptr;
+ temp_bit_matrix_ = nullptr; // Def block matrix.
DCHECK(temp_scoped_alloc_.get() != nullptr);
temp_scoped_alloc_.reset();
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h
index 21b6914..cc215bd 100644
--- a/compiler/dex/mir_graph.h
+++ b/compiler/dex/mir_graph.h
@@ -198,9 +198,7 @@
ArenaBitVector* use_v;
ArenaBitVector* def_v;
ArenaBitVector* live_in_v;
- ArenaBitVector* phi_v;
int32_t* vreg_to_ssa_map_exit;
- ArenaBitVector* ending_check_v; // For null check and class init check elimination.
};
/*
@@ -1261,11 +1259,15 @@
// Stack of the loop head indexes and recalculation flags for RepeatingTopologicalSortIterator.
ArenaVector<std::pair<uint16_t, bool>> topological_order_loop_head_stack_;
int* i_dom_list_;
- ArenaBitVector** def_block_matrix_; // original num registers x num_blocks.
std::unique_ptr<ScopedArenaAllocator> temp_scoped_alloc_;
uint16_t* temp_insn_data_;
uint32_t temp_bit_vector_size_;
ArenaBitVector* temp_bit_vector_;
+ // temp_bit_matrix_ used as one of
+ // - def_block_matrix: original num registers x num_blocks_,
+ // - ending_null_check_matrix: num_blocks_ x original num registers,
+ // - ending_clinit_check_matrix: num_blocks_ x unique class count.
+ ArenaBitVector** temp_bit_matrix_;
std::unique_ptr<GlobalValueNumbering> temp_gvn_;
static const int kInvalidEntry = -1;
ArenaVector<BasicBlock*> block_list_;
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index bf3d7df..322b737 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -825,18 +825,14 @@
return false;
}
- if (kIsDebugBuild) {
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
- CHECK(bb->data_flow_info == nullptr || bb->data_flow_info->ending_check_v == nullptr);
- }
- }
-
DCHECK(temp_scoped_alloc_.get() == nullptr);
temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
temp_bit_vector_size_ = GetNumSSARegs();
temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector(
- temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapTempSSARegisterV);
+ temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapNullCheck);
+ temp_bit_matrix_ = static_cast<ArenaBitVector**>(
+ temp_scoped_alloc_->Alloc(sizeof(ArenaBitVector*) * GetNumBlocks(), kArenaAllocMisc));
+ std::fill_n(temp_bit_matrix_, GetNumBlocks(), nullptr);
return true;
}
@@ -865,8 +861,8 @@
} else if (bb->predecessors.size() == 1) {
BasicBlock* pred_bb = GetBasicBlock(bb->predecessors[0]);
// pred_bb must have already been processed at least once.
- DCHECK(pred_bb->data_flow_info->ending_check_v != nullptr);
- ssa_regs_to_check->Copy(pred_bb->data_flow_info->ending_check_v);
+ DCHECK(temp_bit_matrix_[pred_bb->id] != nullptr);
+ ssa_regs_to_check->Copy(temp_bit_matrix_[pred_bb->id]);
if (pred_bb->block_type == kDalvikByteCode) {
// Check to see if predecessor had an explicit null-check.
MIR* last_insn = pred_bb->last_mir_insn;
@@ -894,14 +890,14 @@
BasicBlock* pred_bb = GetBasicBlock(pred_id);
DCHECK(pred_bb != nullptr);
DCHECK(pred_bb->data_flow_info != nullptr);
- if (pred_bb->data_flow_info->ending_check_v == nullptr) {
+ if (temp_bit_matrix_[pred_bb->id] == nullptr) {
continue;
}
if (!copied_first) {
copied_first = true;
- ssa_regs_to_check->Copy(pred_bb->data_flow_info->ending_check_v);
+ ssa_regs_to_check->Copy(temp_bit_matrix_[pred_bb->id]);
} else {
- ssa_regs_to_check->Union(pred_bb->data_flow_info->ending_check_v);
+ ssa_regs_to_check->Union(temp_bit_matrix_[pred_bb->id]);
}
}
DCHECK(copied_first); // At least one predecessor must have been processed before this bb.
@@ -1015,15 +1011,18 @@
// Did anything change?
bool nce_changed = false;
- if (bb->data_flow_info->ending_check_v == nullptr) {
+ ArenaBitVector* old_ending_ssa_regs_to_check = temp_bit_matrix_[bb->id];
+ if (old_ending_ssa_regs_to_check == nullptr) {
DCHECK(temp_scoped_alloc_.get() != nullptr);
- bb->data_flow_info->ending_check_v = new (temp_scoped_alloc_.get()) ArenaBitVector(
- temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapNullCheck);
nce_changed = ssa_regs_to_check->GetHighestBitSet() != -1;
- bb->data_flow_info->ending_check_v->Copy(ssa_regs_to_check);
- } else if (!ssa_regs_to_check->SameBitsSet(bb->data_flow_info->ending_check_v)) {
+ temp_bit_matrix_[bb->id] = ssa_regs_to_check;
+ // Create a new ssa_regs_to_check for next BB.
+ temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector(
+ temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapNullCheck);
+ } else if (!ssa_regs_to_check->SameBitsSet(old_ending_ssa_regs_to_check)) {
nce_changed = true;
- bb->data_flow_info->ending_check_v->Copy(ssa_regs_to_check);
+ temp_bit_matrix_[bb->id] = ssa_regs_to_check;
+ temp_bit_vector_ = old_ending_ssa_regs_to_check; // Reuse for ssa_regs_to_check for next BB.
}
return nce_changed;
}
@@ -1032,12 +1031,7 @@
// Clean up temporaries.
temp_bit_vector_size_ = 0u;
temp_bit_vector_ = nullptr;
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
- if (bb->data_flow_info != nullptr) {
- bb->data_flow_info->ending_check_v = nullptr;
- }
- }
+ temp_bit_matrix_ = nullptr;
DCHECK(temp_scoped_alloc_.get() != nullptr);
temp_scoped_alloc_.reset();
}
@@ -1067,13 +1061,6 @@
return false;
}
- if (kIsDebugBuild) {
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
- CHECK(bb->data_flow_info == nullptr || bb->data_flow_info->ending_check_v == nullptr);
- }
- }
-
DCHECK(temp_scoped_alloc_.get() == nullptr);
temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
@@ -1147,6 +1134,9 @@
temp_bit_vector_size_ = unique_class_count;
temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector(
temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapClInitCheck);
+ temp_bit_matrix_ = static_cast<ArenaBitVector**>(
+ temp_scoped_alloc_->Alloc(sizeof(ArenaBitVector*) * GetNumBlocks(), kArenaAllocMisc));
+ std::fill_n(temp_bit_matrix_, GetNumBlocks(), nullptr);
DCHECK_GT(temp_bit_vector_size_, 0u);
return true;
}
@@ -1156,7 +1146,7 @@
*/
bool MIRGraph::EliminateClassInitChecks(BasicBlock* bb) {
DCHECK_EQ((cu_->disable_opt & (1 << kClassInitCheckElimination)), 0u);
- if (bb->data_flow_info == NULL) {
+ if (bb->data_flow_info == nullptr) {
return false;
}
@@ -1172,8 +1162,8 @@
// pred_bb must have already been processed at least once.
DCHECK(pred_bb != nullptr);
DCHECK(pred_bb->data_flow_info != nullptr);
- DCHECK(pred_bb->data_flow_info->ending_check_v != nullptr);
- classes_to_check->Copy(pred_bb->data_flow_info->ending_check_v);
+ DCHECK(temp_bit_matrix_[pred_bb->id] != nullptr);
+ classes_to_check->Copy(temp_bit_matrix_[pred_bb->id]);
} else {
// Starting state is union of all incoming arcs.
bool copied_first = false;
@@ -1181,14 +1171,14 @@
BasicBlock* pred_bb = GetBasicBlock(pred_id);
DCHECK(pred_bb != nullptr);
DCHECK(pred_bb->data_flow_info != nullptr);
- if (pred_bb->data_flow_info->ending_check_v == nullptr) {
+ if (temp_bit_matrix_[pred_bb->id] == nullptr) {
continue;
}
if (!copied_first) {
copied_first = true;
- classes_to_check->Copy(pred_bb->data_flow_info->ending_check_v);
+ classes_to_check->Copy(temp_bit_matrix_[pred_bb->id]);
} else {
- classes_to_check->Union(pred_bb->data_flow_info->ending_check_v);
+ classes_to_check->Union(temp_bit_matrix_[pred_bb->id]);
}
}
DCHECK(copied_first); // At least one predecessor must have been processed before this bb.
@@ -1219,16 +1209,18 @@
// Did anything change?
bool changed = false;
- if (bb->data_flow_info->ending_check_v == nullptr) {
+ ArenaBitVector* old_ending_classes_to_check = temp_bit_matrix_[bb->id];
+ if (old_ending_classes_to_check == nullptr) {
DCHECK(temp_scoped_alloc_.get() != nullptr);
- DCHECK(bb->data_flow_info != nullptr);
- bb->data_flow_info->ending_check_v = new (temp_scoped_alloc_.get()) ArenaBitVector(
- temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapClInitCheck);
changed = classes_to_check->GetHighestBitSet() != -1;
- bb->data_flow_info->ending_check_v->Copy(classes_to_check);
- } else if (!classes_to_check->Equal(bb->data_flow_info->ending_check_v)) {
+ temp_bit_matrix_[bb->id] = classes_to_check;
+ // Create a new classes_to_check for next BB.
+ temp_bit_vector_ = new (temp_scoped_alloc_.get()) ArenaBitVector(
+ temp_scoped_alloc_.get(), temp_bit_vector_size_, false, kBitMapClInitCheck);
+ } else if (!classes_to_check->Equal(old_ending_classes_to_check)) {
changed = true;
- bb->data_flow_info->ending_check_v->Copy(classes_to_check);
+ temp_bit_matrix_[bb->id] = classes_to_check;
+ temp_bit_vector_ = old_ending_classes_to_check; // Reuse for classes_to_check for next BB.
}
return changed;
}
@@ -1237,13 +1229,7 @@
// Clean up temporaries.
temp_bit_vector_size_ = 0u;
temp_bit_vector_ = nullptr;
- AllNodesIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
- if (bb->data_flow_info != nullptr) {
- bb->data_flow_info->ending_check_v = nullptr;
- }
- }
-
+ temp_bit_matrix_ = nullptr;
DCHECK(temp_insn_data_ != nullptr);
temp_insn_data_ = nullptr;
DCHECK(temp_scoped_alloc_.get() != nullptr);
diff --git a/compiler/dex/ssa_transformation.cc b/compiler/dex/ssa_transformation.cc
index 3cc573b..4388041 100644
--- a/compiler/dex/ssa_transformation.cc
+++ b/compiler/dex/ssa_transformation.cc
@@ -124,7 +124,7 @@
for (uint32_t idx : bb->data_flow_info->def_v->Indexes()) {
/* Block bb defines register idx */
- def_block_matrix_[idx]->SetBit(bb->id);
+ temp_bit_matrix_[idx]->SetBit(bb->id);
}
return true;
}
@@ -132,15 +132,17 @@
void MIRGraph::ComputeDefBlockMatrix() {
int num_registers = GetNumOfCodeAndTempVRs();
/* Allocate num_registers bit vector pointers */
- def_block_matrix_ = static_cast<ArenaBitVector**>
- (arena_->Alloc(sizeof(ArenaBitVector *) * num_registers,
- kArenaAllocDFInfo));
+ DCHECK(temp_scoped_alloc_ != nullptr);
+ DCHECK(temp_bit_matrix_ == nullptr);
+ temp_bit_matrix_ = static_cast<ArenaBitVector**>(
+ temp_scoped_alloc_->Alloc(sizeof(ArenaBitVector*) * num_registers, kArenaAllocDFInfo));
int i;
/* Initialize num_register vectors with num_blocks bits each */
for (i = 0; i < num_registers; i++) {
- def_block_matrix_[i] =
- new (arena_) ArenaBitVector(arena_, GetNumBlocks(), false, kBitMapBMatrix);
+ temp_bit_matrix_[i] = new (temp_scoped_alloc_.get()) ArenaBitVector(arena_, GetNumBlocks(),
+ false, kBitMapBMatrix);
+ temp_bit_matrix_[i]->ClearAllBits();
}
AllNodesIterator iter(this);
@@ -159,7 +161,7 @@
int num_regs = GetNumOfCodeVRs();
int in_reg = GetFirstInVR();
for (; in_reg < num_regs; in_reg++) {
- def_block_matrix_[in_reg]->SetBit(GetEntryBlock()->id);
+ temp_bit_matrix_[in_reg]->SetBit(GetEntryBlock()->id);
}
}
@@ -478,7 +480,7 @@
/* Iterate through each Dalvik register */
for (dalvik_reg = GetNumOfCodeAndTempVRs() - 1; dalvik_reg >= 0; dalvik_reg--) {
- input_blocks->Copy(def_block_matrix_[dalvik_reg]);
+ input_blocks->Copy(temp_bit_matrix_[dalvik_reg]);
phi_blocks->ClearAllBits();
do {
// TUNING: When we repeat this, we could skip indexes from the previous pass.