blob: 5456f4d0a188e6efe9f17ef39578e42e3bf32d68 [file] [log] [blame]
buzbee2502e002012-12-31 16:05:53 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbee311ca162013-02-28 15:56:43 -080017#include "local_value_numbering.h"
buzbee2502e002012-12-31 16:05:53 -080018
Vladimir Marko95a05972014-05-30 10:01:32 +010019#include "global_value_numbering.h"
Vladimir Markobe0e5462014-02-26 11:24:15 +000020#include "mir_field_info.h"
Vladimir Markof59f18b2014-02-17 15:53:57 +000021#include "mir_graph.h"
22
buzbee2502e002012-12-31 16:05:53 -080023namespace art {
24
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010025namespace { // anonymous namespace
26
27// Operations used for value map keys instead of actual opcode.
Vladimir Marko95a05972014-05-30 10:01:32 +010028static constexpr uint16_t kInvokeMemoryVersionBumpOp = Instruction::INVOKE_VIRTUAL;
29static constexpr uint16_t kUnresolvedSFieldOp = Instruction::SGET;
30static constexpr uint16_t kResolvedSFieldOp = Instruction::SGET_WIDE;
31static constexpr uint16_t kUnresolvedIFieldOp = Instruction::IGET;
32static constexpr uint16_t kNonAliasingIFieldLocOp = Instruction::IGET_WIDE;
33static constexpr uint16_t kNonAliasingIFieldInitialOp = Instruction::IGET_OBJECT;
34static constexpr uint16_t kAliasingIFieldOp = Instruction::IGET_BOOLEAN;
35static constexpr uint16_t kAliasingIFieldStartVersionOp = Instruction::IGET_BYTE;
36static constexpr uint16_t kAliasingIFieldBumpVersionOp = Instruction::IGET_CHAR;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010037static constexpr uint16_t kNonAliasingArrayOp = Instruction::AGET;
38static constexpr uint16_t kNonAliasingArrayStartVersionOp = Instruction::AGET_WIDE;
Vladimir Marko95a05972014-05-30 10:01:32 +010039static constexpr uint16_t kNonAliasingArrayBumpVersionOp = Instruction::AGET_OBJECT;
40static constexpr uint16_t kAliasingArrayOp = Instruction::AGET_BOOLEAN;
41static constexpr uint16_t kAliasingArrayStartVersionOp = Instruction::AGET_BYTE;
42static constexpr uint16_t kAliasingArrayBumpVersionOp = Instruction::AGET_CHAR;
43static constexpr uint16_t kMergeBlockMemoryVersionBumpOp = Instruction::INVOKE_VIRTUAL_RANGE;
44static constexpr uint16_t kMergeBlockAliasingIFieldVersionBumpOp = Instruction::IPUT;
45static constexpr uint16_t kMergeBlockAliasingIFieldMergeLocationOp = Instruction::IPUT_WIDE;
46static constexpr uint16_t kMergeBlockNonAliasingArrayVersionBumpOp = Instruction::APUT;
47static constexpr uint16_t kMergeBlockNonAliasingArrayMergeLocationOp = Instruction::APUT_WIDE;
48static constexpr uint16_t kMergeBlockAliasingArrayVersionBumpOp = Instruction::APUT_OBJECT;
49static constexpr uint16_t kMergeBlockAliasingArrayMergeLocationOp = Instruction::APUT_BOOLEAN;
50static constexpr uint16_t kMergeBlockNonAliasingIFieldVersionBumpOp = Instruction::APUT_BYTE;
51static constexpr uint16_t kMergeBlockSFieldVersionBumpOp = Instruction::APUT_CHAR;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010052
53} // anonymous namespace
54
Vladimir Marko95a05972014-05-30 10:01:32 +010055class LocalValueNumbering::AliasingIFieldVersions {
56 public:
57 static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
58 uint16_t field_id) {
59 uint16_t type = gvn->GetFieldType(field_id);
60 return gvn->LookupValue(kAliasingIFieldStartVersionOp, field_id,
61 lvn->global_memory_version_, lvn->unresolved_ifield_version_[type]);
62 }
63
64 static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
65 uint16_t store_ref_set_id, uint16_t stored_value) {
66 return gvn->LookupValue(kAliasingIFieldBumpVersionOp, old_version,
67 store_ref_set_id, stored_value);
68 }
69
70 static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
71 uint16_t field_id, uint16_t base, uint16_t memory_version) {
72 return gvn->LookupValue(kAliasingIFieldOp, field_id, base, memory_version);
73 }
74
75 static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
76 uint16_t field_id, uint16_t base) {
77 // If the base/field_id is non-aliasing in lvn, use the non-aliasing value.
78 uint16_t type = gvn->GetFieldType(field_id);
79 if (lvn->IsNonAliasingIField(base, field_id, type)) {
80 uint16_t loc = gvn->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
81 auto lb = lvn->non_aliasing_ifield_value_map_.find(loc);
82 return (lb != lvn->non_aliasing_ifield_value_map_.end())
83 ? lb->second
84 : gvn->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
85 }
86 return AliasingValuesMergeGet<AliasingIFieldVersions>(
87 gvn, lvn, &lvn->aliasing_ifield_value_map_, field_id, base);
88 }
89
90 static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
91 uint16_t field_id) {
92 uint16_t type = gvn->GetFieldType(field_id);
93 return lvn->unresolved_ifield_version_[type] == lvn->merge_new_memory_version_ ||
94 lvn->global_memory_version_ == lvn->merge_new_memory_version_;
95 }
96
97 static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
98 uint16_t field_id) {
99 return gvn->LookupValue(kMergeBlockAliasingIFieldVersionBumpOp, field_id, kNoValue, lvn_id);
100 }
101
102 static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
103 uint16_t field_id, uint16_t base) {
104 return gvn->LookupValue(kMergeBlockAliasingIFieldMergeLocationOp, field_id, base, lvn_id);
105 }
106};
107
108class LocalValueNumbering::NonAliasingArrayVersions {
109 public:
110 static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
111 uint16_t array) {
112 return gvn->LookupValue(kNonAliasingArrayStartVersionOp, array, kNoValue, kNoValue);
113 }
114
115 static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
116 uint16_t store_ref_set_id, uint16_t stored_value) {
117 return gvn->LookupValue(kNonAliasingArrayBumpVersionOp, old_version,
118 store_ref_set_id, stored_value);
119 }
120
121 static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
122 uint16_t array, uint16_t index, uint16_t memory_version) {
123 return gvn->LookupValue(kNonAliasingArrayOp, array, index, memory_version);
124 }
125
126 static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
127 uint16_t array, uint16_t index) {
128 return AliasingValuesMergeGet<NonAliasingArrayVersions>(
129 gvn, lvn, &lvn->non_aliasing_array_value_map_, array, index);
130 }
131
132 static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
133 uint16_t array) {
134 return false; // Not affected by global_memory_version_.
135 }
136
137 static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
138 uint16_t array) {
139 return gvn->LookupValue(kMergeBlockNonAliasingArrayVersionBumpOp, array, kNoValue, lvn_id);
140 }
141
142 static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
143 uint16_t array, uint16_t index) {
144 return gvn->LookupValue(kMergeBlockNonAliasingArrayMergeLocationOp, array, index, lvn_id);
145 }
146};
147
148class LocalValueNumbering::AliasingArrayVersions {
149 public:
150 static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
151 uint16_t type) {
152 return gvn->LookupValue(kAliasingArrayStartVersionOp, type, lvn->global_memory_version_,
153 kNoValue);
154 }
155
156 static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
157 uint16_t store_ref_set_id, uint16_t stored_value) {
158 return gvn->LookupValue(kAliasingArrayBumpVersionOp, old_version,
159 store_ref_set_id, stored_value);
160 }
161
162 static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
163 uint16_t type, uint16_t location, uint16_t memory_version) {
164 return gvn->LookupValue(kAliasingArrayOp, type, location, memory_version);
165 }
166
167 static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
168 uint16_t type, uint16_t location) {
169 // If the location is non-aliasing in lvn, use the non-aliasing value.
170 uint16_t array = gvn->GetArrayLocationBase(location);
171 if (lvn->IsNonAliasingArray(array, type)) {
172 uint16_t index = gvn->GetArrayLocationIndex(location);
173 return NonAliasingArrayVersions::LookupMergeValue(gvn, lvn, array, index);
174 }
175 return AliasingValuesMergeGet<AliasingArrayVersions>(
176 gvn, lvn, &lvn->aliasing_array_value_map_, type, location);
177 }
178
179 static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
180 uint16_t type) {
181 return lvn->global_memory_version_ == lvn->merge_new_memory_version_;
182 }
183
184 static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
185 uint16_t type) {
186 return gvn->LookupValue(kMergeBlockAliasingArrayVersionBumpOp, type, kNoValue, lvn_id);
187 }
188
189 static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
190 uint16_t type, uint16_t location) {
191 return gvn->LookupValue(kMergeBlockAliasingArrayMergeLocationOp, type, location, lvn_id);
192 }
193};
194
195template <typename Map>
196LocalValueNumbering::AliasingValues* LocalValueNumbering::GetAliasingValues(
197 Map* map, const typename Map::key_type& key) {
198 auto lb = map->lower_bound(key);
199 if (lb == map->end() || map->key_comp()(key, lb->first)) {
Vladimir Markob19955d2014-07-29 12:04:10 +0100200 lb = map->PutBefore(lb, key, AliasingValues(this));
Vladimir Marko95a05972014-05-30 10:01:32 +0100201 }
202 return &lb->second;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100203}
204
Vladimir Marko95a05972014-05-30 10:01:32 +0100205template <typename Versions, typename KeyType>
206void LocalValueNumbering::UpdateAliasingValuesLoadVersion(const KeyType& key,
207 AliasingValues* values) {
208 if (values->last_load_memory_version == kNoValue) {
209 // Get the start version that accounts for aliasing with unresolved fields of the same
210 // type and make it unique for the field by including the field_id.
211 uint16_t memory_version = values->memory_version_before_stores;
212 if (memory_version == kNoValue) {
213 memory_version = Versions::StartMemoryVersion(gvn_, this, key);
214 }
215 if (!values->store_loc_set.empty()) {
216 uint16_t ref_set_id = gvn_->GetRefSetId(values->store_loc_set);
217 memory_version = Versions::BumpMemoryVersion(gvn_, memory_version, ref_set_id,
218 values->last_stored_value);
219 }
220 values->last_load_memory_version = memory_version;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000221 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100222}
223
224template <typename Versions, typename Map>
225uint16_t LocalValueNumbering::AliasingValuesMergeGet(GlobalValueNumbering* gvn,
226 const LocalValueNumbering* lvn,
227 Map* map, const typename Map::key_type& key,
228 uint16_t location) {
229 // Retrieve the value name that we would get from
230 // const_cast<LocalValueNumbering*>(lvn)->HandleAliasingValueGet(map. key, location)
231 // but don't modify the map.
232 uint16_t value_name;
233 auto it = map->find(key);
234 if (it == map->end()) {
235 uint16_t start_version = Versions::StartMemoryVersion(gvn, lvn, key);
236 value_name = Versions::LookupGlobalValue(gvn, key, location, start_version);
237 } else if (it->second.store_loc_set.count(location) != 0u) {
238 value_name = it->second.last_stored_value;
239 } else {
240 auto load_it = it->second.load_value_map.find(location);
241 if (load_it != it->second.load_value_map.end()) {
242 value_name = load_it->second;
243 } else {
244 value_name = Versions::LookupGlobalValue(gvn, key, location, it->second.last_load_memory_version);
245 }
246 }
247 return value_name;
248}
249
250template <typename Versions, typename Map>
251uint16_t LocalValueNumbering::HandleAliasingValuesGet(Map* map, const typename Map::key_type& key,
252 uint16_t location) {
253 // Retrieve the value name for IGET/SGET/AGET, update the map with new value if any.
254 uint16_t res;
255 AliasingValues* values = GetAliasingValues(map, key);
256 if (values->store_loc_set.count(location) != 0u) {
257 res = values->last_stored_value;
258 } else {
259 UpdateAliasingValuesLoadVersion<Versions>(key, values);
260 auto lb = values->load_value_map.lower_bound(location);
261 if (lb != values->load_value_map.end() && lb->first == location) {
262 res = lb->second;
263 } else {
264 res = Versions::LookupGlobalValue(gvn_, key, location, values->last_load_memory_version);
265 values->load_value_map.PutBefore(lb, location, res);
266 }
267 }
268 return res;
269}
270
271template <typename Versions, typename Map>
272bool LocalValueNumbering::HandleAliasingValuesPut(Map* map, const typename Map::key_type& key,
273 uint16_t location, uint16_t value) {
274 AliasingValues* values = GetAliasingValues(map, key);
275 auto load_values_it = values->load_value_map.find(location);
276 if (load_values_it != values->load_value_map.end() && load_values_it->second == value) {
277 // This insn can be eliminated, it stores the same value that's already in the field.
278 return false;
279 }
280 if (value == values->last_stored_value) {
281 auto store_loc_lb = values->store_loc_set.lower_bound(location);
282 if (store_loc_lb != values->store_loc_set.end() && *store_loc_lb == location) {
283 // This insn can be eliminated, it stores the same value that's already in the field.
284 return false;
285 }
286 values->store_loc_set.emplace_hint(store_loc_lb, location);
287 } else {
288 UpdateAliasingValuesLoadVersion<Versions>(key, values);
289 values->memory_version_before_stores = values->last_load_memory_version;
290 values->last_stored_value = value;
291 values->store_loc_set.clear();
292 values->store_loc_set.insert(location);
293 }
294 // Clear the last load memory version and remove all potentially overwritten values.
295 values->last_load_memory_version = kNoValue;
296 auto it = values->load_value_map.begin(), end = values->load_value_map.end();
297 while (it != end) {
298 if (it->second == value) {
299 ++it;
300 } else {
301 it = values->load_value_map.erase(it);
302 }
303 }
304 return true;
305}
306
Vladimir Markob19955d2014-07-29 12:04:10 +0100307template <typename K>
308void LocalValueNumbering::CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
309 const ScopedArenaSafeMap<K, AliasingValues>& src) {
310 // We need each new AliasingValues (or rather its map members) to be constructed
311 // with our allocator, rather than the allocator of the source.
312 for (const auto& entry : src) {
313 auto it = dest->PutBefore(dest->end(), entry.first, AliasingValues(this));
314 it->second = entry.second; // Map assignments preserve current allocator.
315 }
316}
317
318LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id,
319 ScopedArenaAllocator* allocator)
Vladimir Marko95a05972014-05-30 10:01:32 +0100320 : gvn_(gvn),
321 id_(id),
Vladimir Markob19955d2014-07-29 12:04:10 +0100322 sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
323 sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
324 sfield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
325 non_aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
326 aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
327 non_aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
328 aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
Vladimir Marko95a05972014-05-30 10:01:32 +0100329 global_memory_version_(0u),
Vladimir Markob19955d2014-07-29 12:04:10 +0100330 non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
331 escaped_refs_(std::less<uint16_t>(), allocator->Adapter()),
332 escaped_ifield_clobber_set_(EscapedIFieldClobberKeyComparator(), allocator->Adapter()),
333 escaped_array_clobber_set_(EscapedArrayClobberKeyComparator(), allocator->Adapter()),
334 range_checked_(RangeCheckKeyComparator() , allocator->Adapter()),
335 null_checked_(std::less<uint16_t>(), allocator->Adapter()),
336 merge_names_(allocator->Adapter()),
337 merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), allocator->Adapter()),
Vladimir Marko95a05972014-05-30 10:01:32 +0100338 merge_new_memory_version_(kNoValue) {
339 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
340 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
341}
342
343bool LocalValueNumbering::Equals(const LocalValueNumbering& other) const {
344 DCHECK(gvn_ == other.gvn_);
345 // Compare the maps/sets and memory versions.
346 return sreg_value_map_ == other.sreg_value_map_ &&
347 sreg_wide_value_map_ == other.sreg_wide_value_map_ &&
348 sfield_value_map_ == other.sfield_value_map_ &&
349 non_aliasing_ifield_value_map_ == other.non_aliasing_ifield_value_map_ &&
350 aliasing_ifield_value_map_ == other.aliasing_ifield_value_map_ &&
351 non_aliasing_array_value_map_ == other.non_aliasing_array_value_map_ &&
352 aliasing_array_value_map_ == other.aliasing_array_value_map_ &&
353 SameMemoryVersion(other) &&
354 non_aliasing_refs_ == other.non_aliasing_refs_ &&
355 escaped_refs_ == other.escaped_refs_ &&
356 escaped_ifield_clobber_set_ == other.escaped_ifield_clobber_set_ &&
357 escaped_array_clobber_set_ == other.escaped_array_clobber_set_ &&
358 range_checked_ == other.range_checked_ &&
359 null_checked_ == other.null_checked_;
360}
361
362void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType merge_type) {
Vladimir Markob19955d2014-07-29 12:04:10 +0100363 CopyLiveSregValues(&sreg_value_map_, other.sreg_value_map_);
364 CopyLiveSregValues(&sreg_wide_value_map_, other.sreg_wide_value_map_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100365
366 if (merge_type == kReturnMerge) {
367 // RETURN or PHI+RETURN. We need only sreg value maps.
368 return;
369 }
370
371 non_aliasing_ifield_value_map_ = other.non_aliasing_ifield_value_map_;
Vladimir Markob19955d2014-07-29 12:04:10 +0100372 CopyAliasingValuesMap(&non_aliasing_array_value_map_, other.non_aliasing_array_value_map_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100373 non_aliasing_refs_ = other.non_aliasing_refs_;
374 range_checked_ = other.range_checked_;
375 null_checked_ = other.null_checked_;
376
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100377 const BasicBlock* pred_bb = gvn_->GetBasicBlock(other.Id());
378 if (GlobalValueNumbering::HasNullCheckLastInsn(pred_bb, Id())) {
379 int s_reg = pred_bb->last_mir_insn->ssa_rep->uses[0];
380 null_checked_.insert(other.GetOperandValue(s_reg));
381 }
382
Vladimir Marko95a05972014-05-30 10:01:32 +0100383 if (merge_type == kCatchMerge) {
384 // Memory is clobbered. Use new memory version and don't merge aliasing locations.
385 global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
386 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, global_memory_version_);
387 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, global_memory_version_);
388 PruneNonAliasingRefsForCatch();
389 return;
390 }
391
392 DCHECK(merge_type == kNormalMerge);
393 global_memory_version_ = other.global_memory_version_;
394 std::copy_n(other.unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
395 std::copy_n(other.unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
396 sfield_value_map_ = other.sfield_value_map_;
Vladimir Markob19955d2014-07-29 12:04:10 +0100397 CopyAliasingValuesMap(&aliasing_ifield_value_map_, other.aliasing_ifield_value_map_);
398 CopyAliasingValuesMap(&aliasing_array_value_map_, other.aliasing_array_value_map_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100399 escaped_refs_ = other.escaped_refs_;
400 escaped_ifield_clobber_set_ = other.escaped_ifield_clobber_set_;
401 escaped_array_clobber_set_ = other.escaped_array_clobber_set_;
402}
403
404bool LocalValueNumbering::SameMemoryVersion(const LocalValueNumbering& other) const {
405 return
406 global_memory_version_ == other.global_memory_version_ &&
407 std::equal(unresolved_ifield_version_, unresolved_ifield_version_ + kFieldTypeCount,
408 other.unresolved_ifield_version_) &&
409 std::equal(unresolved_sfield_version_, unresolved_sfield_version_ + kFieldTypeCount,
410 other.unresolved_sfield_version_);
411}
412
413uint16_t LocalValueNumbering::NewMemoryVersion(uint16_t* new_version) {
414 if (*new_version == kNoValue) {
415 *new_version = gvn_->LookupValue(kMergeBlockMemoryVersionBumpOp, 0u, 0u, id_);
416 }
417 return *new_version;
418}
419
420void LocalValueNumbering::MergeMemoryVersions(bool clobbered_catch) {
421 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
422 const LocalValueNumbering* cmp = gvn_->merge_lvns_[0];
423 // Check if the global version has changed.
424 bool new_global_version = clobbered_catch;
425 if (!new_global_version) {
426 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
427 if (lvn->global_memory_version_ != cmp->global_memory_version_) {
428 // Use a new version for everything.
429 new_global_version = true;
430 break;
431 }
432 }
433 }
434 if (new_global_version) {
435 global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
436 std::fill_n(unresolved_sfield_version_, kFieldTypeCount, merge_new_memory_version_);
437 std::fill_n(unresolved_ifield_version_, kFieldTypeCount, merge_new_memory_version_);
438 } else {
439 // Initialize with a copy of memory versions from the comparison LVN.
440 global_memory_version_ = cmp->global_memory_version_;
441 std::copy_n(cmp->unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
442 std::copy_n(cmp->unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
443 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
444 if (lvn == cmp) {
445 continue;
446 }
447 for (size_t i = 0; i != kFieldTypeCount; ++i) {
448 if (lvn->unresolved_ifield_version_[i] != cmp->unresolved_ifield_version_[i]) {
449 unresolved_ifield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
450 }
451 if (lvn->unresolved_sfield_version_[i] != cmp->unresolved_sfield_version_[i]) {
452 unresolved_sfield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
453 }
454 }
455 }
456 }
457}
458
459void LocalValueNumbering::PruneNonAliasingRefsForCatch() {
460 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
461 const BasicBlock* bb = gvn_->GetBasicBlock(lvn->Id());
Vladimir Marko11ca6122014-07-17 20:50:07 +0100462 if (UNLIKELY(bb->taken == id_) || UNLIKELY(bb->fall_through == id_)) {
463 // Non-exceptional path to a catch handler means that the catch block was actually
464 // empty and all exceptional paths lead to the shared path after that empty block.
465 continue;
466 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100467 DCHECK_EQ(bb->taken, kNullBlock);
468 DCHECK_NE(bb->fall_through, kNullBlock);
469 const BasicBlock* fall_through_bb = gvn_->GetBasicBlock(bb->fall_through);
470 const MIR* mir = fall_through_bb->first_mir_insn;
471 DCHECK(mir != nullptr);
472 // Only INVOKEs can leak and clobber non-aliasing references if they throw.
Jean Christophe Beylerfb0ea2d2014-07-29 13:20:42 -0700473 if ((mir->dalvikInsn.FlagsOf() & Instruction::kInvoke) != 0) {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100474 HandleInvokeArgs(mir, lvn);
Vladimir Marko95a05972014-05-30 10:01:32 +0100475 }
476 }
477}
478
479
480template <typename Set, Set LocalValueNumbering::* set_ptr>
481void LocalValueNumbering::IntersectSets() {
482 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
483
484 // Find the LVN with the least entries in the set.
485 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
486 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
487 if ((lvn->*set_ptr).size() < (least_entries_lvn->*set_ptr).size()) {
488 least_entries_lvn = lvn;
489 }
490 }
491
492 // For each key check if it's in all the LVNs.
493 for (const auto& key : least_entries_lvn->*set_ptr) {
494 bool checked = true;
495 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
496 if (lvn != least_entries_lvn && (lvn->*set_ptr).count(key) == 0u) {
497 checked = false;
498 break;
499 }
500 }
501 if (checked) {
502 (this->*set_ptr).emplace_hint((this->*set_ptr).end(), key);
503 }
504 }
505}
506
Vladimir Markob19955d2014-07-29 12:04:10 +0100507void LocalValueNumbering::CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src) {
508 auto dest_end = dest->end();
509 ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
510 DCHECK(live_in_v != nullptr);
511 for (const auto& entry : src) {
512 bool live = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
513 if (live) {
514 dest->PutBefore(dest_end, entry.first, entry.second);
515 }
516 }
517}
518
519template <LocalValueNumbering::SregValueMap LocalValueNumbering::* map_ptr>
520void LocalValueNumbering::IntersectSregValueMaps() {
Vladimir Marko95a05972014-05-30 10:01:32 +0100521 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
522
523 // Find the LVN with the least entries in the set.
524 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
525 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
526 if ((lvn->*map_ptr).size() < (least_entries_lvn->*map_ptr).size()) {
527 least_entries_lvn = lvn;
528 }
529 }
530
531 // For each key check if it's in all the LVNs.
Vladimir Markob19955d2014-07-29 12:04:10 +0100532 ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
533 DCHECK(live_in_v != nullptr);
Vladimir Marko95a05972014-05-30 10:01:32 +0100534 for (const auto& entry : least_entries_lvn->*map_ptr) {
Vladimir Markob19955d2014-07-29 12:04:10 +0100535 bool live_and_same = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
536 if (live_and_same) {
537 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
538 if (lvn != least_entries_lvn) {
539 auto it = (lvn->*map_ptr).find(entry.first);
540 if (it == (lvn->*map_ptr).end() || !(it->second == entry.second)) {
541 live_and_same = false;
542 break;
543 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100544 }
545 }
546 }
Vladimir Markob19955d2014-07-29 12:04:10 +0100547 if (live_and_same) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100548 (this->*map_ptr).PutBefore((this->*map_ptr).end(), entry.first, entry.second);
549 }
550 }
551}
552
553// Intersect maps as sets. The value type must be equality-comparable.
554template <typename Map>
555void LocalValueNumbering::InPlaceIntersectMaps(Map* work_map, const Map& other_map) {
556 auto work_it = work_map->begin(), work_end = work_map->end();
557 auto cmp = work_map->value_comp();
558 for (const auto& entry : other_map) {
559 while (work_it != work_end &&
560 (cmp(*work_it, entry) ||
561 (!cmp(entry, *work_it) && !(work_it->second == entry.second)))) {
562 work_it = work_map->erase(work_it);
563 }
Vladimir Marko55fff042014-07-10 12:42:52 +0100564 if (work_it == work_end) {
565 return;
566 }
567 ++work_it;
Vladimir Marko95a05972014-05-30 10:01:32 +0100568 }
569}
570
571template <typename Set, Set LocalValueNumbering::*set_ptr, void (LocalValueNumbering::*MergeFn)(
572 const typename Set::value_type& entry, typename Set::iterator hint)>
573void LocalValueNumbering::MergeSets() {
574 auto cmp = (this->*set_ptr).value_comp();
575 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
576 auto my_it = (this->*set_ptr).begin(), my_end = (this->*set_ptr).end();
577 for (const auto& entry : lvn->*set_ptr) {
578 while (my_it != my_end && cmp(*my_it, entry)) {
579 ++my_it;
580 }
581 if (my_it != my_end && !cmp(entry, *my_it)) {
582 // Already handled.
583 ++my_it;
584 } else {
585 // Merge values for this field_id.
586 (this->*MergeFn)(entry, my_it); // my_it remains valid across inserts to std::set/SafeMap.
587 }
588 }
589 }
590}
591
592void LocalValueNumbering::IntersectAliasingValueLocations(AliasingValues* work_values,
593 const AliasingValues* values) {
594 auto cmp = work_values->load_value_map.key_comp();
595 auto work_it = work_values->load_value_map.begin(), work_end = work_values->load_value_map.end();
596 auto store_it = values->store_loc_set.begin(), store_end = values->store_loc_set.end();
597 auto load_it = values->load_value_map.begin(), load_end = values->load_value_map.end();
598 while (store_it != store_end || load_it != load_end) {
599 uint16_t loc;
600 if (store_it != store_end && (load_it == load_end || *store_it < load_it->first)) {
601 loc = *store_it;
602 ++store_it;
603 } else {
604 loc = load_it->first;
605 ++load_it;
606 DCHECK(store_it == store_end || cmp(loc, *store_it));
607 }
608 while (work_it != work_end && cmp(work_it->first, loc)) {
609 work_it = work_values->load_value_map.erase(work_it);
610 }
611 if (work_it != work_end && !cmp(loc, work_it->first)) {
612 // The location matches, keep it.
613 ++work_it;
614 }
615 }
616 while (work_it != work_end) {
617 work_it = work_values->load_value_map.erase(work_it);
618 }
619}
620
621void LocalValueNumbering::MergeEscapedRefs(const ValueNameSet::value_type& entry,
622 ValueNameSet::iterator hint) {
623 // See if the ref is either escaped or non-aliasing in each predecessor.
624 bool is_escaped = true;
625 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
626 if (lvn->non_aliasing_refs_.count(entry) == 0u &&
627 lvn->escaped_refs_.count(entry) == 0u) {
628 is_escaped = false;
629 break;
630 }
631 }
632 if (is_escaped) {
633 escaped_refs_.emplace_hint(hint, entry);
634 }
635}
636
637void LocalValueNumbering::MergeEscapedIFieldTypeClobberSets(
638 const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
639 // Insert only type-clobber entries (field_id == kNoValue) of escaped refs.
640 if (entry.field_id == kNoValue && escaped_refs_.count(entry.base) != 0u) {
641 escaped_ifield_clobber_set_.emplace_hint(hint, entry);
642 }
643}
644
645void LocalValueNumbering::MergeEscapedIFieldClobberSets(
646 const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
647 // Insert only those entries of escaped refs that are not overridden by a type clobber.
648 if (!(hint == escaped_ifield_clobber_set_.end() &&
649 hint->base == entry.base && hint->type == entry.type) &&
650 escaped_refs_.count(entry.base) != 0u) {
651 escaped_ifield_clobber_set_.emplace_hint(hint, entry);
652 }
653}
654
655void LocalValueNumbering::MergeEscapedArrayClobberSets(
656 const EscapedArrayClobberSet::value_type& entry, EscapedArrayClobberSet::iterator hint) {
657 if (escaped_refs_.count(entry.base) != 0u) {
658 escaped_array_clobber_set_.emplace_hint(hint, entry);
659 }
660}
661
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100662void LocalValueNumbering::MergeNullChecked() {
663 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
664
665 // Find the LVN with the least entries in the set.
666 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
667 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
668 if (lvn->null_checked_.size() < least_entries_lvn->null_checked_.size()) {
669 least_entries_lvn = lvn;
670 }
671 }
672
673 // For each null-checked value name check if it's null-checked in all the LVNs.
674 for (const auto& value_name : least_entries_lvn->null_checked_) {
675 // Merge null_checked_ for this ref.
676 merge_names_.clear();
677 merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
678 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
679 null_checked_.insert(null_checked_.end(), value_name);
680 }
681 }
682
683 // Now check if the least_entries_lvn has a null-check as the last insn.
684 const BasicBlock* least_entries_bb = gvn_->GetBasicBlock(least_entries_lvn->Id());
685 if (gvn_->HasNullCheckLastInsn(least_entries_bb, id_)) {
686 int s_reg = least_entries_bb->last_mir_insn->ssa_rep->uses[0];
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100687 uint32_t value_name = least_entries_lvn->GetOperandValue(s_reg);
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100688 merge_names_.clear();
689 merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
690 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
691 null_checked_.insert(value_name);
692 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100693 }
694}
695
696void LocalValueNumbering::MergeSFieldValues(const SFieldToValueMap::value_type& entry,
697 SFieldToValueMap::iterator hint) {
698 uint16_t field_id = entry.first;
699 merge_names_.clear();
700 uint16_t value_name = kNoValue;
701 bool same_values = true;
702 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
703 // Get the value name as in HandleSGet() but don't modify *lvn.
704 auto it = lvn->sfield_value_map_.find(field_id);
705 if (it != lvn->sfield_value_map_.end()) {
706 value_name = it->second;
707 } else {
708 uint16_t type = gvn_->GetFieldType(field_id);
709 value_name = gvn_->LookupValue(kResolvedSFieldOp, field_id,
710 lvn->unresolved_sfield_version_[type],
711 lvn->global_memory_version_);
712 }
713
714 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
715 merge_names_.push_back(value_name);
716 }
717 if (same_values) {
718 // value_name already contains the result.
719 } else {
720 auto lb = merge_map_.lower_bound(merge_names_);
721 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
722 value_name = lb->second;
723 } else {
724 value_name = gvn_->LookupValue(kMergeBlockSFieldVersionBumpOp, field_id, id_, kNoValue);
725 merge_map_.PutBefore(lb, merge_names_, value_name);
726 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
727 null_checked_.insert(value_name);
728 }
729 }
730 }
731 sfield_value_map_.PutBefore(hint, field_id, value_name);
732}
733
734void LocalValueNumbering::MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type& entry,
735 IFieldLocToValueMap::iterator hint) {
736 uint16_t field_loc = entry.first;
737 merge_names_.clear();
738 uint16_t value_name = kNoValue;
739 bool same_values = true;
740 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
741 // Get the value name as in HandleIGet() but don't modify *lvn.
742 auto it = lvn->non_aliasing_ifield_value_map_.find(field_loc);
743 if (it != lvn->non_aliasing_ifield_value_map_.end()) {
744 value_name = it->second;
745 } else {
746 value_name = gvn_->LookupValue(kNonAliasingIFieldInitialOp, field_loc, kNoValue, kNoValue);
747 }
748
749 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
750 merge_names_.push_back(value_name);
751 }
752 if (same_values) {
753 // value_name already contains the result.
754 } else {
755 auto lb = merge_map_.lower_bound(merge_names_);
756 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
757 value_name = lb->second;
758 } else {
759 value_name = gvn_->LookupValue(kMergeBlockNonAliasingIFieldVersionBumpOp, field_loc,
760 id_, kNoValue);
761 merge_map_.PutBefore(lb, merge_names_, value_name);
762 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
763 null_checked_.insert(value_name);
764 }
765 }
766 }
767 non_aliasing_ifield_value_map_.PutBefore(hint, field_loc, value_name);
768}
769
770template <typename Map, Map LocalValueNumbering::*map_ptr, typename Versions>
771void LocalValueNumbering::MergeAliasingValues(const typename Map::value_type& entry,
772 typename Map::iterator hint) {
773 const typename Map::key_type& key = entry.first;
774
Vladimir Markob19955d2014-07-29 12:04:10 +0100775 auto it = (this->*map_ptr).PutBefore(hint, key, AliasingValues(this));
Vladimir Marko95a05972014-05-30 10:01:32 +0100776 AliasingValues* my_values = &it->second;
777
778 const AliasingValues* cmp_values = nullptr;
779 bool same_version = !Versions::HasNewBaseVersion(gvn_, this, key);
780 uint16_t load_memory_version_for_same_version = kNoValue;
781 if (same_version) {
782 // Find the first non-null values.
783 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
784 auto it = (lvn->*map_ptr).find(key);
785 if (it != (lvn->*map_ptr).end()) {
786 cmp_values = &it->second;
787 break;
788 }
789 }
790 DCHECK(cmp_values != nullptr); // There must be at least one non-null values.
791
792 // Check if we have identical memory versions, i.e. the global memory version, unresolved
793 // field version and the values' memory_version_before_stores, last_stored_value
794 // and store_loc_set are identical.
795 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
796 auto it = (lvn->*map_ptr).find(key);
797 if (it == (lvn->*map_ptr).end()) {
798 if (cmp_values->memory_version_before_stores != kNoValue) {
799 same_version = false;
800 break;
801 }
802 } else if (cmp_values->last_stored_value != it->second.last_stored_value ||
803 cmp_values->memory_version_before_stores != it->second.memory_version_before_stores ||
804 cmp_values->store_loc_set != it->second.store_loc_set) {
805 same_version = false;
806 break;
807 } else if (it->second.last_load_memory_version != kNoValue) {
808 DCHECK(load_memory_version_for_same_version == kNoValue ||
809 load_memory_version_for_same_version == it->second.last_load_memory_version);
810 load_memory_version_for_same_version = it->second.last_load_memory_version;
811 }
812 }
813 }
814
815 if (same_version) {
816 // Copy the identical values.
817 my_values->memory_version_before_stores = cmp_values->memory_version_before_stores;
818 my_values->last_stored_value = cmp_values->last_stored_value;
819 my_values->store_loc_set = cmp_values->store_loc_set;
820 my_values->last_load_memory_version = load_memory_version_for_same_version;
821 // Merge load values seen in all incoming arcs (i.e. an intersection).
822 if (!cmp_values->load_value_map.empty()) {
823 my_values->load_value_map = cmp_values->load_value_map;
824 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
825 auto it = (lvn->*map_ptr).find(key);
826 if (it == (lvn->*map_ptr).end() || it->second.load_value_map.empty()) {
827 my_values->load_value_map.clear();
828 break;
829 }
830 InPlaceIntersectMaps(&my_values->load_value_map, it->second.load_value_map);
831 if (my_values->load_value_map.empty()) {
832 break;
833 }
834 }
835 }
836 } else {
837 // Bump version number for the merge.
838 my_values->memory_version_before_stores = my_values->last_load_memory_version =
839 Versions::LookupMergeBlockValue(gvn_, id_, key);
840
841 // Calculate the locations that have been either read from or written to in each incoming LVN.
842 bool first_lvn = true;
843 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
844 auto it = (lvn->*map_ptr).find(key);
845 if (it == (lvn->*map_ptr).end()) {
846 my_values->load_value_map.clear();
847 break;
848 }
849 if (first_lvn) {
850 first_lvn = false;
851 // Copy the first LVN's locations. Values will be overwritten later.
852 my_values->load_value_map = it->second.load_value_map;
853 for (uint16_t location : it->second.store_loc_set) {
854 my_values->load_value_map.Put(location, 0u);
855 }
856 } else {
857 IntersectAliasingValueLocations(my_values, &it->second);
858 }
859 }
860 // Calculate merged values for the intersection.
861 for (auto& load_value_entry : my_values->load_value_map) {
862 uint16_t location = load_value_entry.first;
863 bool same_values = true;
864 uint16_t value_name = kNoValue;
865 merge_names_.clear();
866 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
867 value_name = Versions::LookupMergeValue(gvn_, lvn, key, location);
868 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
869 merge_names_.push_back(value_name);
870 }
871 if (same_values) {
872 // value_name already contains the result.
873 } else {
874 auto lb = merge_map_.lower_bound(merge_names_);
875 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
876 value_name = lb->second;
877 } else {
878 // NOTE: In addition to the key and id_ which don't change on an LVN recalculation
879 // during GVN, we also add location which can actually change on recalculation, so the
880 // value_name below may change. This could lead to an infinite loop if the location
881 // value name always changed when the refereced value name changes. However, given that
882 // we assign unique value names for other merges, such as Phis, such a dependency is
883 // not possible in a well-formed SSA graph.
884 value_name = Versions::LookupMergeLocationValue(gvn_, id_, key, location);
885 merge_map_.PutBefore(lb, merge_names_, value_name);
886 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
887 null_checked_.insert(value_name);
888 }
889 }
890 }
891 load_value_entry.second = value_name;
892 }
893 }
894}
895
896void LocalValueNumbering::Merge(MergeType merge_type) {
897 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
898
Vladimir Markob19955d2014-07-29 12:04:10 +0100899 IntersectSregValueMaps<&LocalValueNumbering::sreg_value_map_>();
900 IntersectSregValueMaps<&LocalValueNumbering::sreg_wide_value_map_>();
Vladimir Marko95a05972014-05-30 10:01:32 +0100901 if (merge_type == kReturnMerge) {
902 // RETURN or PHI+RETURN. We need only sreg value maps.
903 return;
904 }
905
906 MergeMemoryVersions(merge_type == kCatchMerge);
907
908 // Merge non-aliasing maps/sets.
Vladimir Marko95a05972014-05-30 10:01:32 +0100909 IntersectSets<ValueNameSet, &LocalValueNumbering::non_aliasing_refs_>();
Vladimir Marko55fff042014-07-10 12:42:52 +0100910 if (!non_aliasing_refs_.empty() && merge_type == kCatchMerge) {
911 PruneNonAliasingRefsForCatch();
912 }
913 if (!non_aliasing_refs_.empty()) {
914 MergeSets<IFieldLocToValueMap, &LocalValueNumbering::non_aliasing_ifield_value_map_,
915 &LocalValueNumbering::MergeNonAliasingIFieldValues>();
916 MergeSets<NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
917 &LocalValueNumbering::MergeAliasingValues<
918 NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
919 NonAliasingArrayVersions>>();
920 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100921
922 // We won't do anything complicated for range checks, just calculate the intersection.
923 IntersectSets<RangeCheckSet, &LocalValueNumbering::range_checked_>();
924
925 // Merge null_checked_. We may later insert more, such as merged object field values.
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100926 MergeNullChecked();
Vladimir Marko95a05972014-05-30 10:01:32 +0100927
928 if (merge_type == kCatchMerge) {
929 // Memory is clobbered. New memory version already created, don't merge aliasing locations.
Vladimir Marko95a05972014-05-30 10:01:32 +0100930 return;
931 }
932
933 DCHECK(merge_type == kNormalMerge);
934
935 // Merge escaped refs and clobber sets.
936 MergeSets<ValueNameSet, &LocalValueNumbering::escaped_refs_,
937 &LocalValueNumbering::MergeEscapedRefs>();
938 if (!escaped_refs_.empty()) {
939 MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
940 &LocalValueNumbering::MergeEscapedIFieldTypeClobberSets>();
941 MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
942 &LocalValueNumbering::MergeEscapedIFieldClobberSets>();
943 MergeSets<EscapedArrayClobberSet, &LocalValueNumbering::escaped_array_clobber_set_,
944 &LocalValueNumbering::MergeEscapedArrayClobberSets>();
945 }
946
947 MergeSets<SFieldToValueMap, &LocalValueNumbering::sfield_value_map_,
948 &LocalValueNumbering::MergeSFieldValues>();
949 MergeSets<AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
950 &LocalValueNumbering::MergeAliasingValues<
951 AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
952 AliasingIFieldVersions>>();
953 MergeSets<AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
954 &LocalValueNumbering::MergeAliasingValues<
955 AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
956 AliasingArrayVersions>>();
Vladimir Markof59f18b2014-02-17 15:53:57 +0000957}
958
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100959void LocalValueNumbering::PrepareEntryBlock() {
960 uint32_t vreg = gvn_->GetMirGraph()->GetFirstInVR();
961 CompilationUnit* cu = gvn_->GetCompilationUnit();
962 const char* shorty = cu->shorty;
963 ++shorty; // Skip return value.
964 if ((cu->access_flags & kAccStatic) == 0) {
965 // If non-static method, mark "this" as non-null
966 uint16_t value_name = GetOperandValue(vreg);
967 ++vreg;
968 null_checked_.insert(value_name);
969 }
970 for ( ; *shorty != 0; ++shorty, ++vreg) {
971 if (*shorty == 'J' || *shorty == 'D') {
972 uint16_t value_name = GetOperandValueWide(vreg);
973 SetOperandValueWide(vreg, value_name);
974 ++vreg;
975 }
976 }
977}
978
Vladimir Markof59f18b2014-02-17 15:53:57 +0000979uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
980 uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000981 DCHECK(null_checked_.find(res) == null_checked_.end());
982 null_checked_.insert(res);
983 non_aliasing_refs_.insert(res);
984 return res;
985}
986
Vladimir Marko95a05972014-05-30 10:01:32 +0100987bool LocalValueNumbering::IsNonAliasing(uint16_t reg) const {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100988 return non_aliasing_refs_.find(reg) != non_aliasing_refs_.end();
Vladimir Markof59f18b2014-02-17 15:53:57 +0000989}
990
Vladimir Marko95a05972014-05-30 10:01:32 +0100991bool LocalValueNumbering::IsNonAliasingIField(uint16_t reg, uint16_t field_id,
992 uint16_t type) const {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100993 if (IsNonAliasing(reg)) {
994 return true;
995 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100996 if (escaped_refs_.find(reg) == escaped_refs_.end()) {
997 return false;
998 }
999 // Check for IPUTs to unresolved fields.
1000 EscapedIFieldClobberKey key1 = { reg, type, kNoValue };
1001 if (escaped_ifield_clobber_set_.find(key1) != escaped_ifield_clobber_set_.end()) {
1002 return false;
1003 }
1004 // Check for aliased IPUTs to the same field.
1005 EscapedIFieldClobberKey key2 = { reg, type, field_id };
1006 return escaped_ifield_clobber_set_.find(key2) == escaped_ifield_clobber_set_.end();
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001007}
1008
Vladimir Marko95a05972014-05-30 10:01:32 +01001009bool LocalValueNumbering::IsNonAliasingArray(uint16_t reg, uint16_t type) const {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001010 if (IsNonAliasing(reg)) {
1011 return true;
1012 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001013 if (escaped_refs_.count(reg) == 0u) {
1014 return false;
1015 }
1016 // Check for aliased APUTs.
1017 EscapedArrayClobberKey key = { reg, type };
1018 return escaped_array_clobber_set_.find(key) == escaped_array_clobber_set_.end();
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001019}
1020
Vladimir Markof59f18b2014-02-17 15:53:57 +00001021void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001022 auto lb = null_checked_.lower_bound(reg);
1023 if (lb != null_checked_.end() && *lb == reg) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001024 if (LIKELY(gvn_->CanModify())) {
1025 if (gvn_->GetCompilationUnit()->verbose) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001026 LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset;
1027 }
1028 mir->optimization_flags |= MIR_IGNORE_NULL_CHECK;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001029 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001030 } else {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001031 null_checked_.insert(lb, reg);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001032 }
1033}
1034
1035void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001036 RangeCheckKey key = { array, index };
1037 auto lb = range_checked_.lower_bound(key);
1038 if (lb != range_checked_.end() && !RangeCheckKeyComparator()(key, *lb)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001039 if (LIKELY(gvn_->CanModify())) {
1040 if (gvn_->GetCompilationUnit()->verbose) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001041 LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
1042 }
1043 mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001044 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001045 } else {
1046 // Mark range check completed.
1047 range_checked_.insert(lb, key);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001048 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001049}
1050
1051void LocalValueNumbering::HandlePutObject(MIR* mir) {
1052 // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
1053 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001054 HandleEscapingRef(base);
1055}
1056
1057void LocalValueNumbering::HandleEscapingRef(uint16_t base) {
1058 auto it = non_aliasing_refs_.find(base);
1059 if (it != non_aliasing_refs_.end()) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001060 non_aliasing_refs_.erase(it);
Vladimir Marko95a05972014-05-30 10:01:32 +01001061 escaped_refs_.insert(base);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001062 }
1063}
1064
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001065void LocalValueNumbering::HandleInvokeArgs(const MIR* mir, const LocalValueNumbering* mir_lvn) {
1066 const int32_t* uses = mir->ssa_rep->uses;
1067 const int32_t* uses_end = uses + mir->ssa_rep->num_uses;
1068 while (uses != uses_end) {
1069 uint16_t sreg = *uses;
1070 ++uses;
1071 // Avoid LookupValue() so that we don't store new values in the global value map.
1072 auto local_it = mir_lvn->sreg_value_map_.find(sreg);
1073 if (local_it != mir_lvn->sreg_value_map_.end()) {
1074 non_aliasing_refs_.erase(local_it->second);
1075 } else {
1076 uint16_t value_name = gvn_->FindValue(kNoValue, sreg, kNoValue, kNoValue);
1077 if (value_name != kNoValue) {
1078 non_aliasing_refs_.erase(value_name);
1079 }
1080 }
1081 }
1082}
1083
Vladimir Marko95a05972014-05-30 10:01:32 +01001084uint16_t LocalValueNumbering::HandlePhi(MIR* mir) {
1085 if (gvn_->merge_lvns_.empty()) {
1086 // Running LVN without a full GVN?
1087 return kNoValue;
1088 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001089 int32_t* uses = mir->ssa_rep->uses;
1090 // Try to find out if this is merging wide regs.
1091 if (mir->ssa_rep->defs[0] != 0 &&
1092 sreg_wide_value_map_.count(mir->ssa_rep->defs[0] - 1) != 0u) {
1093 // This is the high part of a wide reg. Ignore the Phi.
1094 return kNoValue;
1095 }
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001096 BasicBlockId* incoming = mir->meta.phi_incoming;
1097 int16_t pos = 0;
1098 // Check if we're merging a wide value based on the first merged LVN.
1099 const LocalValueNumbering* first_lvn = gvn_->merge_lvns_[0];
1100 DCHECK_LT(pos, mir->ssa_rep->num_uses);
1101 while (incoming[pos] != first_lvn->Id()) {
1102 ++pos;
1103 DCHECK_LT(pos, mir->ssa_rep->num_uses);
Vladimir Marko95a05972014-05-30 10:01:32 +01001104 }
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001105 int first_s_reg = uses[pos];
1106 bool wide = (first_lvn->sreg_wide_value_map_.count(first_s_reg) != 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +01001107 // Iterate over *merge_lvns_ and skip incoming sregs for BBs without associated LVN.
1108 uint16_t value_name = kNoValue;
1109 merge_names_.clear();
Vladimir Marko95a05972014-05-30 10:01:32 +01001110 bool same_values = true;
1111 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
1112 DCHECK_LT(pos, mir->ssa_rep->num_uses);
1113 while (incoming[pos] != lvn->Id()) {
1114 ++pos;
1115 DCHECK_LT(pos, mir->ssa_rep->num_uses);
1116 }
1117 int s_reg = uses[pos];
1118 ++pos;
1119 value_name = wide ? lvn->GetOperandValueWide(s_reg) : lvn->GetOperandValue(s_reg);
1120
1121 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
1122 merge_names_.push_back(value_name);
1123 }
1124 if (same_values) {
1125 // value_name already contains the result.
1126 } else {
1127 auto lb = merge_map_.lower_bound(merge_names_);
1128 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
1129 value_name = lb->second;
1130 } else {
1131 value_name = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
1132 merge_map_.PutBefore(lb, merge_names_, value_name);
1133 if (!wide && gvn_->NullCheckedInAllPredecessors(merge_names_)) {
1134 null_checked_.insert(value_name);
1135 }
1136 }
1137 }
1138 if (wide) {
1139 SetOperandValueWide(mir->ssa_rep->defs[0], value_name);
1140 } else {
1141 SetOperandValue(mir->ssa_rep->defs[0], value_name);
1142 }
1143 return value_name;
1144}
1145
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001146uint16_t LocalValueNumbering::HandleAGet(MIR* mir, uint16_t opcode) {
1147 // uint16_t type = opcode - Instruction::AGET;
1148 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
1149 HandleNullCheck(mir, array);
1150 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
1151 HandleRangeCheck(mir, array, index);
1152 uint16_t type = opcode - Instruction::AGET;
1153 // Establish value number for loaded register.
1154 uint16_t res;
1155 if (IsNonAliasingArray(array, type)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001156 res = HandleAliasingValuesGet<NonAliasingArrayVersions>(&non_aliasing_array_value_map_,
1157 array, index);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001158 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001159 uint16_t location = gvn_->GetArrayLocation(array, index);
1160 res = HandleAliasingValuesGet<AliasingArrayVersions>(&aliasing_array_value_map_,
1161 type, location);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001162 }
1163 if (opcode == Instruction::AGET_WIDE) {
1164 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1165 } else {
1166 SetOperandValue(mir->ssa_rep->defs[0], res);
1167 }
1168 return res;
1169}
1170
1171void LocalValueNumbering::HandleAPut(MIR* mir, uint16_t opcode) {
1172 int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
1173 int index_idx = array_idx + 1;
1174 uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
1175 HandleNullCheck(mir, array);
1176 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
1177 HandleRangeCheck(mir, array, index);
1178
1179 uint16_t type = opcode - Instruction::APUT;
1180 uint16_t value = (opcode == Instruction::APUT_WIDE)
1181 ? GetOperandValueWide(mir->ssa_rep->uses[0])
1182 : GetOperandValue(mir->ssa_rep->uses[0]);
1183 if (IsNonAliasing(array)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001184 bool put_is_live = HandleAliasingValuesPut<NonAliasingArrayVersions>(
1185 &non_aliasing_array_value_map_, array, index, value);
1186 if (!put_is_live) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001187 // This APUT can be eliminated, it stores the same value that's already in the field.
1188 // TODO: Eliminate the APUT.
1189 return;
1190 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001191 } else {
1192 uint16_t location = gvn_->GetArrayLocation(array, index);
1193 bool put_is_live = HandleAliasingValuesPut<AliasingArrayVersions>(
1194 &aliasing_array_value_map_, type, location, value);
1195 if (!put_is_live) {
1196 // This APUT can be eliminated, it stores the same value that's already in the field.
1197 // TODO: Eliminate the APUT.
1198 return;
1199 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001200
Vladimir Marko95a05972014-05-30 10:01:32 +01001201 // Clobber all escaped array refs for this type.
1202 for (uint16_t escaped_array : escaped_refs_) {
1203 EscapedArrayClobberKey clobber_key = { escaped_array, type };
1204 escaped_array_clobber_set_.insert(clobber_key);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001205 }
1206 }
1207}
1208
1209uint16_t LocalValueNumbering::HandleIGet(MIR* mir, uint16_t opcode) {
1210 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
1211 HandleNullCheck(mir, base);
Vladimir Marko95a05972014-05-30 10:01:32 +01001212 const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001213 uint16_t res;
1214 if (!field_info.IsResolved() || field_info.IsVolatile()) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001215 // Unresolved fields may be volatile, so handle them as such to be safe.
Vladimir Markofa236452014-09-29 17:58:10 +01001216 HandleInvokeOrClInitOrAcquireOp(mir); // Volatile GETs have acquire semantics.
1217 // Volatile fields always get a new memory version; field id is irrelevant.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001218 // Use result s_reg - will be unique.
Vladimir Marko95a05972014-05-30 10:01:32 +01001219 res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001220 } else {
1221 uint16_t type = opcode - Instruction::IGET;
Vladimir Marko95a05972014-05-30 10:01:32 +01001222 uint16_t field_id = gvn_->GetFieldId(field_info, type);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001223 if (IsNonAliasingIField(base, field_id, type)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001224 uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
1225 auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
1226 if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
1227 res = lb->second;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001228 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001229 res = gvn_->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
1230 non_aliasing_ifield_value_map_.PutBefore(lb, loc, res);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001231 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001232 } else {
1233 res = HandleAliasingValuesGet<AliasingIFieldVersions>(&aliasing_ifield_value_map_,
1234 field_id, base);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001235 }
1236 }
1237 if (opcode == Instruction::IGET_WIDE) {
1238 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1239 } else {
1240 SetOperandValue(mir->ssa_rep->defs[0], res);
1241 }
1242 return res;
1243}
1244
1245void LocalValueNumbering::HandleIPut(MIR* mir, uint16_t opcode) {
1246 uint16_t type = opcode - Instruction::IPUT;
1247 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
1248 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
1249 HandleNullCheck(mir, base);
Vladimir Marko95a05972014-05-30 10:01:32 +01001250 const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001251 if (!field_info.IsResolved()) {
1252 // Unresolved fields always alias with everything of the same type.
1253 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1254 unresolved_ifield_version_[type] =
Vladimir Marko95a05972014-05-30 10:01:32 +01001255 gvn_->LookupValue(kUnresolvedIFieldOp, kNoValue, kNoValue, mir->offset);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001256
Vladimir Marko95a05972014-05-30 10:01:32 +01001257 // For simplicity, treat base as escaped now.
1258 HandleEscapingRef(base);
1259
1260 // Clobber all fields of escaped references of the same type.
1261 for (uint16_t escaped_ref : escaped_refs_) {
1262 EscapedIFieldClobberKey clobber_key = { escaped_ref, type, kNoValue };
1263 escaped_ifield_clobber_set_.insert(clobber_key);
1264 }
1265
1266 // Aliasing fields of the same type may have been overwritten.
1267 auto it = aliasing_ifield_value_map_.begin(), end = aliasing_ifield_value_map_.end();
1268 while (it != end) {
1269 if (gvn_->GetFieldType(it->first) != type) {
1270 ++it;
1271 } else {
1272 it = aliasing_ifield_value_map_.erase(it);
1273 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001274 }
1275 } else if (field_info.IsVolatile()) {
1276 // Nothing to do, resolved volatile fields always get a new memory version anyway and
1277 // can't alias with resolved non-volatile fields.
1278 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001279 uint16_t field_id = gvn_->GetFieldId(field_info, type);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001280 uint16_t value = (opcode == Instruction::IPUT_WIDE)
1281 ? GetOperandValueWide(mir->ssa_rep->uses[0])
1282 : GetOperandValue(mir->ssa_rep->uses[0]);
1283 if (IsNonAliasing(base)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001284 uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
1285 auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
1286 if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
1287 if (lb->second == value) {
1288 // This IPUT can be eliminated, it stores the same value that's already in the field.
1289 // TODO: Eliminate the IPUT.
1290 return;
1291 }
1292 lb->second = value; // Overwrite.
1293 } else {
1294 non_aliasing_ifield_value_map_.PutBefore(lb, loc, value);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001295 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001296 } else {
1297 bool put_is_live = HandleAliasingValuesPut<AliasingIFieldVersions>(
1298 &aliasing_ifield_value_map_, field_id, base, value);
1299 if (!put_is_live) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001300 // This IPUT can be eliminated, it stores the same value that's already in the field.
1301 // TODO: Eliminate the IPUT.
1302 return;
1303 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001304
Vladimir Marko95a05972014-05-30 10:01:32 +01001305 // Clobber all fields of escaped references for this field.
1306 for (uint16_t escaped_ref : escaped_refs_) {
1307 EscapedIFieldClobberKey clobber_key = { escaped_ref, type, field_id };
1308 escaped_ifield_clobber_set_.insert(clobber_key);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001309 }
1310 }
1311 }
1312}
1313
1314uint16_t LocalValueNumbering::HandleSGet(MIR* mir, uint16_t opcode) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001315 const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
Vladimir Markofa236452014-09-29 17:58:10 +01001316 if (!field_info.IsResolved() || field_info.IsVolatile() ||
1317 (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0)) {
1318 // Volatile SGETs (and unresolved fields are potentially volatile) have acquire semantics
1319 // and class initialization can call arbitrary functions, we need to wipe aliasing values.
1320 HandleInvokeOrClInitOrAcquireOp(mir);
Vladimir Markof418f322014-07-09 14:45:36 +01001321 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001322 uint16_t res;
1323 if (!field_info.IsResolved() || field_info.IsVolatile()) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001324 // Unresolved fields may be volatile, so handle them as such to be safe.
Vladimir Markofa236452014-09-29 17:58:10 +01001325 // Volatile fields always get a new memory version; field id is irrelevant.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001326 // Use result s_reg - will be unique.
Vladimir Marko95a05972014-05-30 10:01:32 +01001327 res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001328 } else {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001329 uint16_t type = opcode - Instruction::SGET;
Vladimir Marko95a05972014-05-30 10:01:32 +01001330 uint16_t field_id = gvn_->GetFieldId(field_info, type);
1331 auto lb = sfield_value_map_.lower_bound(field_id);
1332 if (lb != sfield_value_map_.end() && lb->first == field_id) {
1333 res = lb->second;
1334 } else {
1335 // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
1336 // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
1337 // to determine the version of the field.
1338 res = gvn_->LookupValue(kResolvedSFieldOp, field_id,
1339 unresolved_sfield_version_[type], global_memory_version_);
1340 sfield_value_map_.PutBefore(lb, field_id, res);
1341 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001342 }
1343 if (opcode == Instruction::SGET_WIDE) {
1344 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1345 } else {
1346 SetOperandValue(mir->ssa_rep->defs[0], res);
1347 }
1348 return res;
1349}
1350
1351void LocalValueNumbering::HandleSPut(MIR* mir, uint16_t opcode) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001352 const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
Vladimir Markof418f322014-07-09 14:45:36 +01001353 if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
1354 // Class initialization can call arbitrary functions, we need to wipe aliasing values.
Vladimir Markofa236452014-09-29 17:58:10 +01001355 HandleInvokeOrClInitOrAcquireOp(mir);
Vladimir Markof418f322014-07-09 14:45:36 +01001356 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001357 uint16_t type = opcode - Instruction::SPUT;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001358 if (!field_info.IsResolved()) {
1359 // Unresolved fields always alias with everything of the same type.
1360 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1361 unresolved_sfield_version_[type] =
Vladimir Marko95a05972014-05-30 10:01:32 +01001362 gvn_->LookupValue(kUnresolvedSFieldOp, kNoValue, kNoValue, mir->offset);
1363 RemoveSFieldsForType(type);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001364 } else if (field_info.IsVolatile()) {
1365 // Nothing to do, resolved volatile fields always get a new memory version anyway and
1366 // can't alias with resolved non-volatile fields.
1367 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001368 uint16_t field_id = gvn_->GetFieldId(field_info, type);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001369 uint16_t value = (opcode == Instruction::SPUT_WIDE)
1370 ? GetOperandValueWide(mir->ssa_rep->uses[0])
1371 : GetOperandValue(mir->ssa_rep->uses[0]);
1372 // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
1373 // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
1374 // to determine the version of the field.
Vladimir Marko95a05972014-05-30 10:01:32 +01001375 auto lb = sfield_value_map_.lower_bound(field_id);
1376 if (lb != sfield_value_map_.end() && lb->first == field_id) {
1377 if (lb->second == value) {
1378 // This SPUT can be eliminated, it stores the same value that's already in the field.
1379 // TODO: Eliminate the SPUT.
1380 return;
1381 }
1382 lb->second = value; // Overwrite.
1383 } else {
1384 sfield_value_map_.PutBefore(lb, field_id, value);
1385 }
1386 }
1387}
1388
1389void LocalValueNumbering::RemoveSFieldsForType(uint16_t type) {
1390 // Erase all static fields of this type from the sfield_value_map_.
1391 for (auto it = sfield_value_map_.begin(), end = sfield_value_map_.end(); it != end; ) {
1392 if (gvn_->GetFieldType(it->first) == type) {
1393 it = sfield_value_map_.erase(it);
1394 } else {
1395 ++it;
1396 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001397 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001398}
buzbee2502e002012-12-31 16:05:53 -08001399
Vladimir Markofa236452014-09-29 17:58:10 +01001400void LocalValueNumbering::HandleInvokeOrClInitOrAcquireOp(MIR* mir) {
Vladimir Markof418f322014-07-09 14:45:36 +01001401 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
Vladimir Marko95a05972014-05-30 10:01:32 +01001402 global_memory_version_ =
1403 gvn_->LookupValue(kInvokeMemoryVersionBumpOp, 0u, 0u, mir->offset);
1404 // All static fields and instance fields and array elements of aliasing references,
1405 // including escaped references, may have been modified.
1406 sfield_value_map_.clear();
1407 aliasing_ifield_value_map_.clear();
1408 aliasing_array_value_map_.clear();
1409 escaped_refs_.clear();
1410 escaped_ifield_clobber_set_.clear();
1411 escaped_array_clobber_set_.clear();
Vladimir Markof418f322014-07-09 14:45:36 +01001412}
1413
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07001414uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001415 uint16_t res = kNoValue;
buzbee2502e002012-12-31 16:05:53 -08001416 uint16_t opcode = mir->dalvikInsn.opcode;
1417 switch (opcode) {
1418 case Instruction::NOP:
1419 case Instruction::RETURN_VOID:
1420 case Instruction::RETURN:
1421 case Instruction::RETURN_OBJECT:
1422 case Instruction::RETURN_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001423 case Instruction::GOTO:
1424 case Instruction::GOTO_16:
1425 case Instruction::GOTO_32:
1426 case Instruction::CHECK_CAST:
1427 case Instruction::THROW:
1428 case Instruction::FILL_ARRAY_DATA:
buzbee2502e002012-12-31 16:05:53 -08001429 case Instruction::PACKED_SWITCH:
1430 case Instruction::SPARSE_SWITCH:
1431 case Instruction::IF_EQ:
1432 case Instruction::IF_NE:
1433 case Instruction::IF_LT:
1434 case Instruction::IF_GE:
1435 case Instruction::IF_GT:
1436 case Instruction::IF_LE:
1437 case Instruction::IF_EQZ:
1438 case Instruction::IF_NEZ:
1439 case Instruction::IF_LTZ:
1440 case Instruction::IF_GEZ:
1441 case Instruction::IF_GTZ:
1442 case Instruction::IF_LEZ:
buzbee2502e002012-12-31 16:05:53 -08001443 case kMirOpFusedCmplFloat:
1444 case kMirOpFusedCmpgFloat:
1445 case kMirOpFusedCmplDouble:
1446 case kMirOpFusedCmpgDouble:
1447 case kMirOpFusedCmpLong:
1448 // Nothing defined - take no action.
1449 break;
1450
Vladimir Marko95a05972014-05-30 10:01:32 +01001451 case Instruction::MONITOR_ENTER:
1452 HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
Vladimir Markofa236452014-09-29 17:58:10 +01001453 HandleInvokeOrClInitOrAcquireOp(mir); // Acquire operation.
Vladimir Marko95a05972014-05-30 10:01:32 +01001454 break;
1455
1456 case Instruction::MONITOR_EXIT:
1457 HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
1458 // If we're running GVN and CanModify(), uneliminated null check indicates bytecode error.
Vladimir Marko415ac882014-09-30 18:09:14 +01001459 if ((mir->optimization_flags & MIR_IGNORE_NULL_CHECK) == 0 &&
1460 gvn_->work_lvn_ != nullptr && gvn_->CanModify()) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001461 LOG(WARNING) << "Bytecode error: MONITOR_EXIT is still null checked at 0x" << std::hex
1462 << mir->offset << " in " << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file);
1463 }
1464 break;
1465
Vladimir Markof59f18b2014-02-17 15:53:57 +00001466 case Instruction::FILLED_NEW_ARRAY:
1467 case Instruction::FILLED_NEW_ARRAY_RANGE:
1468 // Nothing defined but the result will be unique and non-null.
1469 if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001470 uint16_t array = MarkNonAliasingNonNull(mir->next);
1471 // Do not SetOperandValue(), we'll do that when we process the MOVE_RESULT_OBJECT.
1472 if (kLocalValueNumberingEnableFilledNewArrayTracking && mir->ssa_rep->num_uses != 0u) {
1473 AliasingValues* values = GetAliasingValues(&non_aliasing_array_value_map_, array);
1474 // Clear the value if we got a merged version in a loop.
Vladimir Markob19955d2014-07-29 12:04:10 +01001475 *values = AliasingValues(this);
Vladimir Marko95a05972014-05-30 10:01:32 +01001476 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1477 DCHECK_EQ(High16Bits(i), 0u);
1478 uint16_t index = gvn_->LookupValue(Instruction::CONST, i, 0u, 0);
1479 uint16_t value = GetOperandValue(mir->ssa_rep->uses[i]);
1480 values->load_value_map.Put(index, value);
1481 RangeCheckKey key = { array, index };
1482 range_checked_.insert(key);
1483 }
1484 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001485 // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
1486 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001487 // All args escaped (if references).
1488 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1489 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
1490 HandleEscapingRef(reg);
1491 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001492 break;
1493
Vladimir Markoa78e66a2014-10-16 13:38:44 +01001494 case kMirOpNullCheck:
1495 HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
1496 break;
1497
Vladimir Markof59f18b2014-02-17 15:53:57 +00001498 case Instruction::INVOKE_DIRECT:
1499 case Instruction::INVOKE_DIRECT_RANGE:
1500 case Instruction::INVOKE_VIRTUAL:
1501 case Instruction::INVOKE_VIRTUAL_RANGE:
1502 case Instruction::INVOKE_SUPER:
1503 case Instruction::INVOKE_SUPER_RANGE:
1504 case Instruction::INVOKE_INTERFACE:
1505 case Instruction::INVOKE_INTERFACE_RANGE: {
1506 // Nothing defined but handle the null check.
1507 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
1508 HandleNullCheck(mir, reg);
1509 }
Ian Rogersfc787ec2014-10-09 21:56:44 -07001510 FALLTHROUGH_INTENDED;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001511 case Instruction::INVOKE_STATIC:
1512 case Instruction::INVOKE_STATIC_RANGE:
Vladimir Markoff0ac472014-10-02 17:24:53 +01001513 // Make ref args aliasing.
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001514 HandleInvokeArgs(mir, this);
Vladimir Markoff0ac472014-10-02 17:24:53 +01001515 HandleInvokeOrClInitOrAcquireOp(mir);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001516 break;
1517
buzbee2502e002012-12-31 16:05:53 -08001518 case Instruction::MOVE_RESULT:
1519 case Instruction::MOVE_RESULT_OBJECT:
1520 case Instruction::INSTANCE_OF:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001521 // 1 result, treat as unique each time, use result s_reg - will be unique.
1522 res = GetOperandValue(mir->ssa_rep->defs[0]);
1523 SetOperandValue(mir->ssa_rep->defs[0], res);
1524 break;
1525 case Instruction::MOVE_EXCEPTION:
buzbee2502e002012-12-31 16:05:53 -08001526 case Instruction::NEW_INSTANCE:
buzbee2502e002012-12-31 16:05:53 -08001527 case Instruction::CONST_CLASS:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001528 case Instruction::NEW_ARRAY:
Vladimir Markob3e527b2014-04-04 12:37:07 +01001529 // 1 result, treat as unique each time, use result s_reg - will be unique.
1530 res = MarkNonAliasingNonNull(mir);
Vladimir Marko95a05972014-05-30 10:01:32 +01001531 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001532 break;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001533 case Instruction::CONST_STRING:
1534 case Instruction::CONST_STRING_JUMBO:
1535 // These strings are internalized, so assign value based on the string pool index.
Vladimir Marko95a05972014-05-30 10:01:32 +01001536 res = gvn_->LookupValue(Instruction::CONST_STRING, Low16Bits(mir->dalvikInsn.vB),
1537 High16Bits(mir->dalvikInsn.vB), 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001538 SetOperandValue(mir->ssa_rep->defs[0], res);
1539 null_checked_.insert(res); // May already be there.
1540 // NOTE: Hacking the contents of an internalized string via reflection is possible
1541 // but the behavior is undefined. Therefore, we consider the string constant and
1542 // the reference non-aliasing.
1543 // TUNING: We could keep this property even if the reference "escapes".
1544 non_aliasing_refs_.insert(res); // May already be there.
1545 break;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001546 case Instruction::MOVE_RESULT_WIDE:
Vladimir Markob3e527b2014-04-04 12:37:07 +01001547 // 1 wide result, treat as unique each time, use result s_reg - will be unique.
1548 res = GetOperandValueWide(mir->ssa_rep->defs[0]);
1549 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001550 break;
1551
1552 case kMirOpPhi:
Vladimir Marko95a05972014-05-30 10:01:32 +01001553 res = HandlePhi(mir);
buzbee2502e002012-12-31 16:05:53 -08001554 break;
1555
1556 case Instruction::MOVE:
1557 case Instruction::MOVE_OBJECT:
1558 case Instruction::MOVE_16:
1559 case Instruction::MOVE_OBJECT_16:
1560 case Instruction::MOVE_FROM16:
1561 case Instruction::MOVE_OBJECT_FROM16:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001562 case kMirOpCopy:
1563 // Just copy value number of source to value number of result.
1564 res = GetOperandValue(mir->ssa_rep->uses[0]);
1565 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001566 break;
1567
1568 case Instruction::MOVE_WIDE:
1569 case Instruction::MOVE_WIDE_16:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001570 case Instruction::MOVE_WIDE_FROM16:
1571 // Just copy value number of source to value number of result.
1572 res = GetOperandValueWide(mir->ssa_rep->uses[0]);
1573 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001574 break;
1575
1576 case Instruction::CONST:
1577 case Instruction::CONST_4:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001578 case Instruction::CONST_16:
Vladimir Marko95a05972014-05-30 10:01:32 +01001579 res = gvn_->LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
1580 High16Bits(mir->dalvikInsn.vB), 0);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001581 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001582 break;
1583
Vladimir Markof59f18b2014-02-17 15:53:57 +00001584 case Instruction::CONST_HIGH16:
Vladimir Marko95a05972014-05-30 10:01:32 +01001585 res = gvn_->LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001586 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001587 break;
1588
1589 case Instruction::CONST_WIDE_16:
1590 case Instruction::CONST_WIDE_32: {
Vladimir Marko95a05972014-05-30 10:01:32 +01001591 uint16_t low_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
1592 High16Bits(mir->dalvikInsn.vB >> 16), 1);
buzbee2502e002012-12-31 16:05:53 -08001593 uint16_t high_res;
1594 if (mir->dalvikInsn.vB & 0x80000000) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001595 high_res = gvn_->LookupValue(Instruction::CONST, 0xffff, 0xffff, 2);
buzbee2502e002012-12-31 16:05:53 -08001596 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001597 high_res = gvn_->LookupValue(Instruction::CONST, 0, 0, 2);
buzbee2502e002012-12-31 16:05:53 -08001598 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001599 res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001600 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001601 }
1602 break;
1603
1604 case Instruction::CONST_WIDE: {
1605 uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide);
1606 uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide);
Vladimir Marko95a05972014-05-30 10:01:32 +01001607 uint16_t low_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(low_word),
1608 High16Bits(low_word), 1);
1609 uint16_t high_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(high_word),
1610 High16Bits(high_word), 2);
1611 res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -08001612 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1613 }
1614 break;
1615
1616 case Instruction::CONST_WIDE_HIGH16: {
Vladimir Marko95a05972014-05-30 10:01:32 +01001617 uint16_t low_res = gvn_->LookupValue(Instruction::CONST, 0, 0, 1);
1618 uint16_t high_res = gvn_->LookupValue(Instruction::CONST, 0,
1619 Low16Bits(mir->dalvikInsn.vB), 2);
1620 res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3);
buzbee2502e002012-12-31 16:05:53 -08001621 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1622 }
1623 break;
1624
Vladimir Marko95a05972014-05-30 10:01:32 +01001625 case Instruction::ARRAY_LENGTH: {
1626 // Handle the null check.
1627 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
1628 HandleNullCheck(mir, reg);
1629 }
Ian Rogersfc787ec2014-10-09 21:56:44 -07001630 FALLTHROUGH_INTENDED;
buzbee2502e002012-12-31 16:05:53 -08001631 case Instruction::NEG_INT:
1632 case Instruction::NOT_INT:
1633 case Instruction::NEG_FLOAT:
1634 case Instruction::INT_TO_BYTE:
1635 case Instruction::INT_TO_SHORT:
1636 case Instruction::INT_TO_CHAR:
1637 case Instruction::INT_TO_FLOAT:
1638 case Instruction::FLOAT_TO_INT: {
1639 // res = op + 1 operand
1640 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001641 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001642 SetOperandValue(mir->ssa_rep->defs[0], res);
1643 }
1644 break;
1645
1646 case Instruction::LONG_TO_FLOAT:
1647 case Instruction::LONG_TO_INT:
1648 case Instruction::DOUBLE_TO_FLOAT:
1649 case Instruction::DOUBLE_TO_INT: {
1650 // res = op + 1 wide operand
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001651 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001652 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001653 SetOperandValue(mir->ssa_rep->defs[0], res);
1654 }
1655 break;
1656
buzbee2502e002012-12-31 16:05:53 -08001657 case Instruction::DOUBLE_TO_LONG:
1658 case Instruction::LONG_TO_DOUBLE:
1659 case Instruction::NEG_LONG:
1660 case Instruction::NOT_LONG:
1661 case Instruction::NEG_DOUBLE: {
1662 // wide res = op + 1 wide operand
1663 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001664 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001665 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1666 }
1667 break;
1668
1669 case Instruction::FLOAT_TO_DOUBLE:
1670 case Instruction::FLOAT_TO_LONG:
1671 case Instruction::INT_TO_DOUBLE:
1672 case Instruction::INT_TO_LONG: {
1673 // wide res = op + 1 operand
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001674 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001675 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001676 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1677 }
1678 break;
1679
1680 case Instruction::CMPL_DOUBLE:
1681 case Instruction::CMPG_DOUBLE:
1682 case Instruction::CMP_LONG: {
1683 // res = op + 2 wide operands
1684 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1685 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001686 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001687 SetOperandValue(mir->ssa_rep->defs[0], res);
1688 }
1689 break;
1690
1691 case Instruction::CMPG_FLOAT:
1692 case Instruction::CMPL_FLOAT:
1693 case Instruction::ADD_INT:
1694 case Instruction::ADD_INT_2ADDR:
1695 case Instruction::MUL_INT:
1696 case Instruction::MUL_INT_2ADDR:
1697 case Instruction::AND_INT:
1698 case Instruction::AND_INT_2ADDR:
1699 case Instruction::OR_INT:
1700 case Instruction::OR_INT_2ADDR:
1701 case Instruction::XOR_INT:
1702 case Instruction::XOR_INT_2ADDR:
1703 case Instruction::SUB_INT:
1704 case Instruction::SUB_INT_2ADDR:
1705 case Instruction::DIV_INT:
1706 case Instruction::DIV_INT_2ADDR:
1707 case Instruction::REM_INT:
1708 case Instruction::REM_INT_2ADDR:
1709 case Instruction::SHL_INT:
1710 case Instruction::SHL_INT_2ADDR:
1711 case Instruction::SHR_INT:
1712 case Instruction::SHR_INT_2ADDR:
1713 case Instruction::USHR_INT:
1714 case Instruction::USHR_INT_2ADDR: {
1715 // res = op + 2 operands
1716 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1717 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001718 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001719 SetOperandValue(mir->ssa_rep->defs[0], res);
1720 }
1721 break;
1722
1723 case Instruction::ADD_LONG:
1724 case Instruction::SUB_LONG:
1725 case Instruction::MUL_LONG:
1726 case Instruction::DIV_LONG:
1727 case Instruction::REM_LONG:
1728 case Instruction::AND_LONG:
1729 case Instruction::OR_LONG:
1730 case Instruction::XOR_LONG:
1731 case Instruction::ADD_LONG_2ADDR:
1732 case Instruction::SUB_LONG_2ADDR:
1733 case Instruction::MUL_LONG_2ADDR:
1734 case Instruction::DIV_LONG_2ADDR:
1735 case Instruction::REM_LONG_2ADDR:
1736 case Instruction::AND_LONG_2ADDR:
1737 case Instruction::OR_LONG_2ADDR:
1738 case Instruction::XOR_LONG_2ADDR:
1739 case Instruction::ADD_DOUBLE:
1740 case Instruction::SUB_DOUBLE:
1741 case Instruction::MUL_DOUBLE:
1742 case Instruction::DIV_DOUBLE:
1743 case Instruction::REM_DOUBLE:
1744 case Instruction::ADD_DOUBLE_2ADDR:
1745 case Instruction::SUB_DOUBLE_2ADDR:
1746 case Instruction::MUL_DOUBLE_2ADDR:
1747 case Instruction::DIV_DOUBLE_2ADDR:
1748 case Instruction::REM_DOUBLE_2ADDR: {
1749 // wide res = op + 2 wide operands
1750 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1751 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001752 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001753 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1754 }
1755 break;
1756
1757 case Instruction::SHL_LONG:
1758 case Instruction::SHR_LONG:
1759 case Instruction::USHR_LONG:
1760 case Instruction::SHL_LONG_2ADDR:
1761 case Instruction::SHR_LONG_2ADDR:
1762 case Instruction::USHR_LONG_2ADDR: {
1763 // wide res = op + 1 wide operand + 1 operand
1764 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001765 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[2]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001766 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001767 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1768 }
1769 break;
1770
1771 case Instruction::ADD_FLOAT:
1772 case Instruction::SUB_FLOAT:
1773 case Instruction::MUL_FLOAT:
1774 case Instruction::DIV_FLOAT:
1775 case Instruction::REM_FLOAT:
1776 case Instruction::ADD_FLOAT_2ADDR:
1777 case Instruction::SUB_FLOAT_2ADDR:
1778 case Instruction::MUL_FLOAT_2ADDR:
1779 case Instruction::DIV_FLOAT_2ADDR:
1780 case Instruction::REM_FLOAT_2ADDR: {
1781 // res = op + 2 operands
1782 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1783 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001784 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001785 SetOperandValue(mir->ssa_rep->defs[0], res);
1786 }
1787 break;
1788
1789 case Instruction::RSUB_INT:
1790 case Instruction::ADD_INT_LIT16:
1791 case Instruction::MUL_INT_LIT16:
1792 case Instruction::DIV_INT_LIT16:
1793 case Instruction::REM_INT_LIT16:
1794 case Instruction::AND_INT_LIT16:
1795 case Instruction::OR_INT_LIT16:
1796 case Instruction::XOR_INT_LIT16:
1797 case Instruction::ADD_INT_LIT8:
1798 case Instruction::RSUB_INT_LIT8:
1799 case Instruction::MUL_INT_LIT8:
1800 case Instruction::DIV_INT_LIT8:
1801 case Instruction::REM_INT_LIT8:
1802 case Instruction::AND_INT_LIT8:
1803 case Instruction::OR_INT_LIT8:
1804 case Instruction::XOR_INT_LIT8:
1805 case Instruction::SHL_INT_LIT8:
1806 case Instruction::SHR_INT_LIT8:
1807 case Instruction::USHR_INT_LIT8: {
nikolay serdjukee40aa42014-03-25 12:21:29 +07001808 // Same as res = op + 2 operands, except use vC as operand 2
buzbee2502e002012-12-31 16:05:53 -08001809 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001810 uint16_t operand2 = gvn_->LookupValue(Instruction::CONST, mir->dalvikInsn.vC, 0, 0);
1811 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001812 SetOperandValue(mir->ssa_rep->defs[0], res);
1813 }
1814 break;
1815
buzbee2502e002012-12-31 16:05:53 -08001816 case Instruction::AGET_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001817 case Instruction::AGET:
1818 case Instruction::AGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001819 case Instruction::AGET_BOOLEAN:
1820 case Instruction::AGET_BYTE:
1821 case Instruction::AGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001822 case Instruction::AGET_SHORT:
1823 res = HandleAGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001824 break;
1825
buzbee2502e002012-12-31 16:05:53 -08001826 case Instruction::APUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001827 HandlePutObject(mir);
Ian Rogersfc787ec2014-10-09 21:56:44 -07001828 FALLTHROUGH_INTENDED;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001829 case Instruction::APUT:
1830 case Instruction::APUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001831 case Instruction::APUT_BYTE:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001832 case Instruction::APUT_BOOLEAN:
1833 case Instruction::APUT_SHORT:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001834 case Instruction::APUT_CHAR:
1835 HandleAPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001836 break;
1837
1838 case Instruction::IGET_OBJECT:
buzbee2502e002012-12-31 16:05:53 -08001839 case Instruction::IGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001840 case Instruction::IGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001841 case Instruction::IGET_BOOLEAN:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001842 case Instruction::IGET_BYTE:
1843 case Instruction::IGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001844 case Instruction::IGET_SHORT:
1845 res = HandleIGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001846 break;
1847
buzbee2502e002012-12-31 16:05:53 -08001848 case Instruction::IPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001849 HandlePutObject(mir);
Ian Rogersfc787ec2014-10-09 21:56:44 -07001850 FALLTHROUGH_INTENDED;
buzbee2502e002012-12-31 16:05:53 -08001851 case Instruction::IPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001852 case Instruction::IPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001853 case Instruction::IPUT_BOOLEAN:
1854 case Instruction::IPUT_BYTE:
1855 case Instruction::IPUT_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001856 case Instruction::IPUT_SHORT:
1857 HandleIPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001858 break;
1859
1860 case Instruction::SGET_OBJECT:
1861 case Instruction::SGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001862 case Instruction::SGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001863 case Instruction::SGET_BOOLEAN:
1864 case Instruction::SGET_BYTE:
1865 case Instruction::SGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001866 case Instruction::SGET_SHORT:
1867 res = HandleSGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001868 break;
1869
1870 case Instruction::SPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001871 HandlePutObject(mir);
Ian Rogersfc787ec2014-10-09 21:56:44 -07001872 FALLTHROUGH_INTENDED;
buzbee2502e002012-12-31 16:05:53 -08001873 case Instruction::SPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001874 case Instruction::SPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001875 case Instruction::SPUT_BOOLEAN:
1876 case Instruction::SPUT_BYTE:
1877 case Instruction::SPUT_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001878 case Instruction::SPUT_SHORT:
1879 HandleSPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001880 break;
buzbee2502e002012-12-31 16:05:53 -08001881 }
1882 return res;
1883}
1884
1885} // namespace art