summaryrefslogtreecommitdiffstats
path: root/compiler/dex/local_value_numbering.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/dex/local_value_numbering.cc')
-rw-r--r--compiler/dex/local_value_numbering.cc108
1 files changed, 64 insertions, 44 deletions
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index 0e072ec..5997568 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -197,11 +197,7 @@ LocalValueNumbering::AliasingValues* LocalValueNumbering::GetAliasingValues(
Map* map, const typename Map::key_type& key) {
auto lb = map->lower_bound(key);
if (lb == map->end() || map->key_comp()(key, lb->first)) {
- map->PutBefore(lb, key, AliasingValues(gvn_->allocator_));
- // The new entry was inserted before lb.
- DCHECK(lb != map->begin());
- --lb;
- DCHECK(!map->key_comp()(lb->first, key) && !map->key_comp()(key, lb->first));
+ lb = map->PutBefore(lb, key, AliasingValues(this));
}
return &lb->second;
}
@@ -308,25 +304,37 @@ bool LocalValueNumbering::HandleAliasingValuesPut(Map* map, const typename Map::
return true;
}
-LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id)
+template <typename K>
+void LocalValueNumbering::CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
+ const ScopedArenaSafeMap<K, AliasingValues>& src) {
+ // We need each new AliasingValues (or rather its map members) to be constructed
+ // with our allocator, rather than the allocator of the source.
+ for (const auto& entry : src) {
+ auto it = dest->PutBefore(dest->end(), entry.first, AliasingValues(this));
+ it->second = entry.second; // Map assignments preserve current allocator.
+ }
+}
+
+LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id,
+ ScopedArenaAllocator* allocator)
: gvn_(gvn),
id_(id),
- sreg_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- sreg_wide_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- sfield_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- non_aliasing_ifield_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- aliasing_ifield_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- non_aliasing_array_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- aliasing_array_value_map_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
+ sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
+ sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
+ sfield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
+ non_aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
+ aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
+ non_aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
+ aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
global_memory_version_(0u),
- non_aliasing_refs_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- escaped_refs_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- escaped_ifield_clobber_set_(EscapedIFieldClobberKeyComparator(), gvn->Allocator()->Adapter()),
- escaped_array_clobber_set_(EscapedArrayClobberKeyComparator(), gvn->Allocator()->Adapter()),
- range_checked_(RangeCheckKeyComparator() , gvn->Allocator()->Adapter()),
- null_checked_(std::less<uint16_t>(), gvn->Allocator()->Adapter()),
- merge_names_(gvn->Allocator()->Adapter()),
- merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), gvn->Allocator()->Adapter()),
+ non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
+ escaped_refs_(std::less<uint16_t>(), allocator->Adapter()),
+ escaped_ifield_clobber_set_(EscapedIFieldClobberKeyComparator(), allocator->Adapter()),
+ escaped_array_clobber_set_(EscapedArrayClobberKeyComparator(), allocator->Adapter()),
+ range_checked_(RangeCheckKeyComparator() , allocator->Adapter()),
+ null_checked_(std::less<uint16_t>(), allocator->Adapter()),
+ merge_names_(allocator->Adapter()),
+ merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), allocator->Adapter()),
merge_new_memory_version_(kNoValue) {
std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
@@ -352,8 +360,8 @@ bool LocalValueNumbering::Equals(const LocalValueNumbering& other) const {
}
void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType merge_type) {
- sreg_value_map_ = other.sreg_value_map_;
- sreg_wide_value_map_ = other.sreg_wide_value_map_;
+ CopyLiveSregValues(&sreg_value_map_, other.sreg_value_map_);
+ CopyLiveSregValues(&sreg_wide_value_map_, other.sreg_wide_value_map_);
if (merge_type == kReturnMerge) {
// RETURN or PHI+RETURN. We need only sreg value maps.
@@ -361,7 +369,7 @@ void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType m
}
non_aliasing_ifield_value_map_ = other.non_aliasing_ifield_value_map_;
- non_aliasing_array_value_map_ = other.non_aliasing_array_value_map_;
+ CopyAliasingValuesMap(&non_aliasing_array_value_map_, other.non_aliasing_array_value_map_);
non_aliasing_refs_ = other.non_aliasing_refs_;
range_checked_ = other.range_checked_;
null_checked_ = other.null_checked_;
@@ -380,8 +388,8 @@ void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType m
std::copy_n(other.unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
std::copy_n(other.unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
sfield_value_map_ = other.sfield_value_map_;
- aliasing_ifield_value_map_ = other.aliasing_ifield_value_map_;
- aliasing_array_value_map_ = other.aliasing_array_value_map_;
+ CopyAliasingValuesMap(&aliasing_ifield_value_map_, other.aliasing_ifield_value_map_);
+ CopyAliasingValuesMap(&aliasing_array_value_map_, other.aliasing_array_value_map_);
escaped_refs_ = other.escaped_refs_;
escaped_ifield_clobber_set_ = other.escaped_ifield_clobber_set_;
escaped_array_clobber_set_ = other.escaped_array_clobber_set_;
@@ -493,8 +501,20 @@ void LocalValueNumbering::IntersectSets() {
}
}
-template <typename Map, Map LocalValueNumbering::* map_ptr>
-void LocalValueNumbering::IntersectMaps() {
+void LocalValueNumbering::CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src) {
+ auto dest_end = dest->end();
+ ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
+ DCHECK(live_in_v != nullptr);
+ for (const auto& entry : src) {
+ bool live = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
+ if (live) {
+ dest->PutBefore(dest_end, entry.first, entry.second);
+ }
+ }
+}
+
+template <LocalValueNumbering::SregValueMap LocalValueNumbering::* map_ptr>
+void LocalValueNumbering::IntersectSregValueMaps() {
DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
// Find the LVN with the least entries in the set.
@@ -506,18 +526,22 @@ void LocalValueNumbering::IntersectMaps() {
}
// For each key check if it's in all the LVNs.
+ ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
+ DCHECK(live_in_v != nullptr);
for (const auto& entry : least_entries_lvn->*map_ptr) {
- bool checked = true;
- for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
- if (lvn != least_entries_lvn) {
- auto it = (lvn->*map_ptr).find(entry.first);
- if (it == (lvn->*map_ptr).end() || !(it->second == entry.second)) {
- checked = false;
- break;
+ bool live_and_same = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
+ if (live_and_same) {
+ for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
+ if (lvn != least_entries_lvn) {
+ auto it = (lvn->*map_ptr).find(entry.first);
+ if (it == (lvn->*map_ptr).end() || !(it->second == entry.second)) {
+ live_and_same = false;
+ break;
+ }
}
}
}
- if (checked) {
+ if (live_and_same) {
(this->*map_ptr).PutBefore((this->*map_ptr).end(), entry.first, entry.second);
}
}
@@ -721,11 +745,7 @@ void LocalValueNumbering::MergeAliasingValues(const typename Map::value_type& en
typename Map::iterator hint) {
const typename Map::key_type& key = entry.first;
- (this->*map_ptr).PutBefore(hint, key, AliasingValues(gvn_->allocator_));
- DCHECK(hint != (this->*map_ptr).begin());
- AliasingIFieldValuesMap::iterator it = hint;
- --it;
- DCHECK_EQ(it->first, key);
+ auto it = (this->*map_ptr).PutBefore(hint, key, AliasingValues(this));
AliasingValues* my_values = &it->second;
const AliasingValues* cmp_values = nullptr;
@@ -849,8 +869,8 @@ void LocalValueNumbering::MergeAliasingValues(const typename Map::value_type& en
void LocalValueNumbering::Merge(MergeType merge_type) {
DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
- IntersectMaps<SregValueMap, &LocalValueNumbering::sreg_value_map_>();
- IntersectMaps<SregValueMap, &LocalValueNumbering::sreg_wide_value_map_>();
+ IntersectSregValueMaps<&LocalValueNumbering::sreg_value_map_>();
+ IntersectSregValueMaps<&LocalValueNumbering::sreg_wide_value_map_>();
if (merge_type == kReturnMerge) {
// RETURN or PHI+RETURN. We need only sreg value maps.
return;
@@ -1385,7 +1405,7 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
if (kLocalValueNumberingEnableFilledNewArrayTracking && mir->ssa_rep->num_uses != 0u) {
AliasingValues* values = GetAliasingValues(&non_aliasing_array_value_map_, array);
// Clear the value if we got a merged version in a loop.
- *values = AliasingValues(gvn_->allocator_);
+ *values = AliasingValues(this);
for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
DCHECK_EQ(High16Bits(i), 0u);
uint16_t index = gvn_->LookupValue(Instruction::CONST, i, 0u, 0);