Improve GVN performance when merging null-checked values.
And ignore the limit on maximum number of processed basic
blocks once the GVN has actually converged and we're just
applying optimizations.
Bug: 16398693
Change-Id: Ie5aa0386ea4e0e9ae2bbf13963e2424e1713b22f
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index 5997568..8b02269 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -656,13 +656,37 @@
}
}
-void LocalValueNumbering::MergeNullChecked(const ValueNameSet::value_type& entry,
- ValueNameSet::iterator hint) {
- // Merge null_checked_ for this ref.
- merge_names_.clear();
- merge_names_.resize(gvn_->merge_lvns_.size(), entry);
- if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
- null_checked_.insert(hint, entry);
+void LocalValueNumbering::MergeNullChecked() {
+ DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
+
+ // Find the LVN with the least entries in the set.
+ const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
+ for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
+ if (lvn->null_checked_.size() < least_entries_lvn->null_checked_.size()) {
+ least_entries_lvn = lvn;
+ }
+ }
+
+ // For each null-checked value name check if it's null-checked in all the LVNs.
+ for (const auto& value_name : least_entries_lvn->null_checked_) {
+ // Merge null_checked_ for this ref.
+ merge_names_.clear();
+ merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
+ if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
+ null_checked_.insert(null_checked_.end(), value_name);
+ }
+ }
+
+ // Now check if the least_entries_lvn has a null-check as the last insn.
+ const BasicBlock* least_entries_bb = gvn_->GetBasicBlock(least_entries_lvn->Id());
+ if (gvn_->HasNullCheckLastInsn(least_entries_bb, id_)) {
+ int s_reg = least_entries_bb->last_mir_insn->ssa_rep->uses[0];
+ uint32_t value_name = least_entries_lvn->GetSRegValueName(s_reg);
+ merge_names_.clear();
+ merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
+ if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
+ null_checked_.insert(value_name);
+ }
}
}
@@ -896,8 +920,7 @@
IntersectSets<RangeCheckSet, &LocalValueNumbering::range_checked_>();
// Merge null_checked_. We may later insert more, such as merged object field values.
- MergeSets<ValueNameSet, &LocalValueNumbering::null_checked_,
- &LocalValueNumbering::MergeNullChecked>();
+ MergeNullChecked();
if (merge_type == kCatchMerge) {
// Memory is clobbered. New memory version already created, don't merge aliasing locations.