summaryrefslogtreecommitdiff
path: root/compiler/dex/mir_optimization.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/dex/mir_optimization.cc')
-rw-r--r--compiler/dex/mir_optimization.cc65
1 files changed, 62 insertions, 3 deletions
diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc
index 6566e03682..dc1057f277 100644
--- a/compiler/dex/mir_optimization.cc
+++ b/compiler/dex/mir_optimization.cc
@@ -15,8 +15,10 @@
*/
#include "compiler_internals.h"
+#include "global_value_numbering.h"
#include "local_value_numbering.h"
#include "dataflow_iterator-inl.h"
+#include "dex/global_value_numbering.h"
#include "dex/quick/dex_file_method_inliner.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "utils/scoped_arena_containers.h"
@@ -318,12 +320,15 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) {
if (bb->block_type == kDead) {
return true;
}
- bool use_lvn = bb->use_lvn;
+ // Don't do a separate LVN if we did the GVN.
+ bool use_lvn = bb->use_lvn && (cu_->disable_opt & (1 << kGlobalValueNumbering)) != 0;
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));
- local_valnum.reset(new (allocator.get()) LocalValueNumbering(cu_, allocator.get()));
+ global_valnum.reset(new (allocator.get()) GlobalValueNumbering(cu_, allocator.get()));
+ local_valnum.reset(new (allocator.get()) LocalValueNumbering(global_valnum.get(), bb->id));
}
while (bb != NULL) {
for (MIR* mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
@@ -558,7 +563,7 @@ bool MIRGraph::BasicBlockOpt(BasicBlock* bb) {
}
bb = ((cu_->disable_opt & (1 << kSuppressExceptionEdges)) != 0) ? NextDominatedBlock(bb) : NULL;
}
- if (use_lvn && UNLIKELY(!local_valnum->Good())) {
+ if (use_lvn && UNLIKELY(!global_valnum->Good())) {
LOG(WARNING) << "LVN overflow in " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
}
@@ -1136,6 +1141,60 @@ void MIRGraph::EliminateClassInitChecksEnd() {
temp_scoped_alloc_.reset();
}
+bool MIRGraph::ApplyGlobalValueNumberingGate() {
+ if ((cu_->disable_opt & (1 << kGlobalValueNumbering)) != 0) {
+ return false;
+ }
+
+ if ((merged_df_flags_ & DF_LVN) == 0) {
+ return false;
+ }
+
+ DCHECK(temp_scoped_alloc_ == nullptr);
+ 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()));
+ return true;
+}
+
+bool MIRGraph::ApplyGlobalValueNumbering(BasicBlock* bb) {
+ DCHECK(temp_gvn_ != nullptr);
+ LocalValueNumbering* lvn = temp_gvn_->PrepareBasicBlock(bb);
+ if (lvn != nullptr) {
+ for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) {
+ lvn->GetValueNumber(mir);
+ }
+ }
+ bool change = (lvn != nullptr) && temp_gvn_->FinishBasicBlock(bb);
+ return change;
+}
+
+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()) {
+ LocalValueNumbering* lvn = temp_gvn_->PrepareBasicBlock(bb);
+ 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);
+ }
+ }
+ } else {
+ LOG(WARNING) << "GVN failed for " << PrettyMethod(cu_->method_idx, *cu_->dex_file);
+ }
+
+ DCHECK(temp_gvn_ != nullptr);
+ temp_gvn_.reset();
+ DCHECK(temp_scoped_alloc_ != nullptr);
+ temp_scoped_alloc_.reset();
+}
+
void MIRGraph::ComputeInlineIFieldLoweringInfo(uint16_t field_idx, MIR* invoke, MIR* iget_or_iput) {
uint32_t method_index = invoke->meta.method_lowering_info;
if (temp_bit_vector_->IsBitSet(method_index)) {