Quick: In GVN, apply modifications early if outside loop.
To improve GVN performance, apply modifications to blocks
outside loops during the initial convergence phase. During
the post processing phase, apply modifications only to the
blocks belonging to loops.
Also clean up the check whether to run the LVN and add the
capability to limit the maximum number of nested loops we
allow the GVN to process.
Change-Id: Ie7f1254f91a442397c06a325d5d314d8f58e5012
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 00528e5..96505ab 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -408,14 +408,14 @@
if (bb->block_type == kDead) {
return true;
}
- // Don't do a separate LVN if we did the GVN.
- bool use_lvn = bb->use_lvn && (cu_->disable_opt & (1u << kGlobalValueNumbering)) != 0u;
+ bool use_lvn = bb->use_lvn && (cu_->disable_opt & (1u << kLocalValueNumbering)) == 0u;
std::unique_ptr<ScopedArenaAllocator> allocator;
std::unique_ptr<GlobalValueNumbering> global_valnum;
std::unique_ptr<LocalValueNumbering> local_valnum;
if (use_lvn) {
allocator.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
- global_valnum.reset(new (allocator.get()) GlobalValueNumbering(cu_, allocator.get()));
+ global_valnum.reset(new (allocator.get()) GlobalValueNumbering(cu_, allocator.get(),
+ GlobalValueNumbering::kModeLvn));
local_valnum.reset(new (allocator.get()) LocalValueNumbering(global_valnum.get(), bb->id,
allocator.get()));
}
@@ -1297,7 +1297,7 @@
}
bool MIRGraph::ApplyGlobalValueNumberingGate() {
- if ((cu_->disable_opt & (1u << kGlobalValueNumbering)) != 0u) {
+ if (GlobalValueNumbering::Skip(cu_)) {
return false;
}
@@ -1305,7 +1305,8 @@
temp_scoped_alloc_.reset(ScopedArenaAllocator::Create(&cu_->arena_stack));
DCHECK(temp_gvn_ == nullptr);
temp_gvn_.reset(
- new (temp_scoped_alloc_.get()) GlobalValueNumbering(cu_, temp_scoped_alloc_.get()));
+ new (temp_scoped_alloc_.get()) GlobalValueNumbering(cu_, temp_scoped_alloc_.get(),
+ GlobalValueNumbering::kModeGvn));
return true;
}
@@ -1324,19 +1325,23 @@
void MIRGraph::ApplyGlobalValueNumberingEnd() {
// Perform modifications.
if (temp_gvn_->Good()) {
- temp_gvn_->AllowModifications();
- PreOrderDfsIterator iter(this);
- for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
- ScopedArenaAllocator allocator(&cu_->arena_stack); // Reclaim memory after each LVN.
- LocalValueNumbering* lvn = temp_gvn_->PrepareBasicBlock(bb, &allocator);
- if (lvn != nullptr) {
- for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
- lvn->GetValueNumber(mir);
+ if (max_nested_loops_ != 0u) {
+ temp_gvn_->StartPostProcessing();
+ TopologicalSortIterator iter(this);
+ for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) {
+ ScopedArenaAllocator allocator(&cu_->arena_stack); // Reclaim memory after each LVN.
+ LocalValueNumbering* lvn = temp_gvn_->PrepareBasicBlock(bb, &allocator);
+ if (lvn != nullptr) {
+ for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
+ lvn->GetValueNumber(mir);
+ }
+ bool change = temp_gvn_->FinishBasicBlock(bb);
+ DCHECK(!change) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
}
- bool change = temp_gvn_->FinishBasicBlock(bb);
- DCHECK(!change) << PrettyMethod(cu_->method_idx, *cu_->dex_file);
}
}
+ // GVN was successful, running the LVN would be useless.
+ cu_->disable_opt |= (1u << kLocalValueNumbering);
} else {
LOG(WARNING) << "GVN failed for " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
}