blob: cc9dbe4adb19ea0c5407b4c1c7c56012dfe3e66a [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) {
Vladimir Markoaf6925b2014-10-31 16:37:32 +000059 uint16_t type = gvn->GetIFieldType(field_id);
Vladimir Marko95a05972014-05-30 10:01:32 +010060 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.
Vladimir Markoaf6925b2014-10-31 16:37:32 +000078 uint16_t type = gvn->GetIFieldType(field_id);
Vladimir Marko95a05972014-05-30 10:01:32 +010079 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) {
Vladimir Markoaf6925b2014-10-31 16:37:32 +000092 uint16_t type = gvn->GetIFieldType(field_id);
Vladimir Marko95a05972014-05-30 10:01:32 +010093 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:
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700110 static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn,
111 const LocalValueNumbering* lvn ATTRIBUTE_UNUSED,
Vladimir Marko95a05972014-05-30 10:01:32 +0100112 uint16_t array) {
113 return gvn->LookupValue(kNonAliasingArrayStartVersionOp, array, kNoValue, kNoValue);
114 }
115
116 static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
117 uint16_t store_ref_set_id, uint16_t stored_value) {
118 return gvn->LookupValue(kNonAliasingArrayBumpVersionOp, old_version,
119 store_ref_set_id, stored_value);
120 }
121
122 static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
123 uint16_t array, uint16_t index, uint16_t memory_version) {
124 return gvn->LookupValue(kNonAliasingArrayOp, array, index, memory_version);
125 }
126
127 static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
128 uint16_t array, uint16_t index) {
129 return AliasingValuesMergeGet<NonAliasingArrayVersions>(
130 gvn, lvn, &lvn->non_aliasing_array_value_map_, array, index);
131 }
132
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700133 static bool HasNewBaseVersion(GlobalValueNumbering* gvn ATTRIBUTE_UNUSED,
134 const LocalValueNumbering* lvn ATTRIBUTE_UNUSED,
135 uint16_t array ATTRIBUTE_UNUSED) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100136 return false; // Not affected by global_memory_version_.
137 }
138
139 static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
140 uint16_t array) {
141 return gvn->LookupValue(kMergeBlockNonAliasingArrayVersionBumpOp, array, kNoValue, lvn_id);
142 }
143
144 static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
145 uint16_t array, uint16_t index) {
146 return gvn->LookupValue(kMergeBlockNonAliasingArrayMergeLocationOp, array, index, lvn_id);
147 }
148};
149
150class LocalValueNumbering::AliasingArrayVersions {
151 public:
152 static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
153 uint16_t type) {
154 return gvn->LookupValue(kAliasingArrayStartVersionOp, type, lvn->global_memory_version_,
155 kNoValue);
156 }
157
158 static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
159 uint16_t store_ref_set_id, uint16_t stored_value) {
160 return gvn->LookupValue(kAliasingArrayBumpVersionOp, old_version,
161 store_ref_set_id, stored_value);
162 }
163
164 static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
165 uint16_t type, uint16_t location, uint16_t memory_version) {
166 return gvn->LookupValue(kAliasingArrayOp, type, location, memory_version);
167 }
168
Andreas Gampeca714582015-04-03 19:41:34 -0700169 static uint16_t LookupMergeValue(GlobalValueNumbering* gvn,
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700170 const LocalValueNumbering* lvn,
Andreas Gampeca714582015-04-03 19:41:34 -0700171 uint16_t type, uint16_t location) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100172 // If the location is non-aliasing in lvn, use the non-aliasing value.
173 uint16_t array = gvn->GetArrayLocationBase(location);
174 if (lvn->IsNonAliasingArray(array, type)) {
175 uint16_t index = gvn->GetArrayLocationIndex(location);
176 return NonAliasingArrayVersions::LookupMergeValue(gvn, lvn, array, index);
177 }
178 return AliasingValuesMergeGet<AliasingArrayVersions>(
179 gvn, lvn, &lvn->aliasing_array_value_map_, type, location);
180 }
181
Ian Rogers6a3c1fc2014-10-31 00:33:20 -0700182 static bool HasNewBaseVersion(GlobalValueNumbering* gvn ATTRIBUTE_UNUSED,
183 const LocalValueNumbering* lvn,
184 uint16_t type ATTRIBUTE_UNUSED) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100185 return lvn->global_memory_version_ == lvn->merge_new_memory_version_;
186 }
187
188 static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
189 uint16_t type) {
190 return gvn->LookupValue(kMergeBlockAliasingArrayVersionBumpOp, type, kNoValue, lvn_id);
191 }
192
193 static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
194 uint16_t type, uint16_t location) {
195 return gvn->LookupValue(kMergeBlockAliasingArrayMergeLocationOp, type, location, lvn_id);
196 }
197};
198
199template <typename Map>
200LocalValueNumbering::AliasingValues* LocalValueNumbering::GetAliasingValues(
201 Map* map, const typename Map::key_type& key) {
202 auto lb = map->lower_bound(key);
203 if (lb == map->end() || map->key_comp()(key, lb->first)) {
Vladimir Markob19955d2014-07-29 12:04:10 +0100204 lb = map->PutBefore(lb, key, AliasingValues(this));
Vladimir Marko95a05972014-05-30 10:01:32 +0100205 }
206 return &lb->second;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100207}
208
Vladimir Marko95a05972014-05-30 10:01:32 +0100209template <typename Versions, typename KeyType>
210void LocalValueNumbering::UpdateAliasingValuesLoadVersion(const KeyType& key,
211 AliasingValues* values) {
212 if (values->last_load_memory_version == kNoValue) {
213 // Get the start version that accounts for aliasing with unresolved fields of the same
214 // type and make it unique for the field by including the field_id.
215 uint16_t memory_version = values->memory_version_before_stores;
216 if (memory_version == kNoValue) {
217 memory_version = Versions::StartMemoryVersion(gvn_, this, key);
218 }
219 if (!values->store_loc_set.empty()) {
220 uint16_t ref_set_id = gvn_->GetRefSetId(values->store_loc_set);
221 memory_version = Versions::BumpMemoryVersion(gvn_, memory_version, ref_set_id,
222 values->last_stored_value);
223 }
224 values->last_load_memory_version = memory_version;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000225 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100226}
227
228template <typename Versions, typename Map>
229uint16_t LocalValueNumbering::AliasingValuesMergeGet(GlobalValueNumbering* gvn,
230 const LocalValueNumbering* lvn,
231 Map* map, const typename Map::key_type& key,
232 uint16_t location) {
233 // Retrieve the value name that we would get from
234 // const_cast<LocalValueNumbering*>(lvn)->HandleAliasingValueGet(map. key, location)
235 // but don't modify the map.
236 uint16_t value_name;
237 auto it = map->find(key);
238 if (it == map->end()) {
239 uint16_t start_version = Versions::StartMemoryVersion(gvn, lvn, key);
240 value_name = Versions::LookupGlobalValue(gvn, key, location, start_version);
241 } else if (it->second.store_loc_set.count(location) != 0u) {
242 value_name = it->second.last_stored_value;
243 } else {
244 auto load_it = it->second.load_value_map.find(location);
245 if (load_it != it->second.load_value_map.end()) {
246 value_name = load_it->second;
247 } else {
248 value_name = Versions::LookupGlobalValue(gvn, key, location, it->second.last_load_memory_version);
249 }
250 }
251 return value_name;
252}
253
254template <typename Versions, typename Map>
255uint16_t LocalValueNumbering::HandleAliasingValuesGet(Map* map, const typename Map::key_type& key,
256 uint16_t location) {
257 // Retrieve the value name for IGET/SGET/AGET, update the map with new value if any.
258 uint16_t res;
259 AliasingValues* values = GetAliasingValues(map, key);
260 if (values->store_loc_set.count(location) != 0u) {
261 res = values->last_stored_value;
262 } else {
263 UpdateAliasingValuesLoadVersion<Versions>(key, values);
264 auto lb = values->load_value_map.lower_bound(location);
265 if (lb != values->load_value_map.end() && lb->first == location) {
266 res = lb->second;
267 } else {
268 res = Versions::LookupGlobalValue(gvn_, key, location, values->last_load_memory_version);
269 values->load_value_map.PutBefore(lb, location, res);
270 }
271 }
272 return res;
273}
274
275template <typename Versions, typename Map>
276bool LocalValueNumbering::HandleAliasingValuesPut(Map* map, const typename Map::key_type& key,
277 uint16_t location, uint16_t value) {
278 AliasingValues* values = GetAliasingValues(map, key);
279 auto load_values_it = values->load_value_map.find(location);
280 if (load_values_it != values->load_value_map.end() && load_values_it->second == value) {
281 // This insn can be eliminated, it stores the same value that's already in the field.
282 return false;
283 }
284 if (value == values->last_stored_value) {
285 auto store_loc_lb = values->store_loc_set.lower_bound(location);
286 if (store_loc_lb != values->store_loc_set.end() && *store_loc_lb == location) {
287 // This insn can be eliminated, it stores the same value that's already in the field.
288 return false;
289 }
290 values->store_loc_set.emplace_hint(store_loc_lb, location);
291 } else {
292 UpdateAliasingValuesLoadVersion<Versions>(key, values);
293 values->memory_version_before_stores = values->last_load_memory_version;
294 values->last_stored_value = value;
295 values->store_loc_set.clear();
296 values->store_loc_set.insert(location);
297 }
298 // Clear the last load memory version and remove all potentially overwritten values.
299 values->last_load_memory_version = kNoValue;
300 auto it = values->load_value_map.begin(), end = values->load_value_map.end();
301 while (it != end) {
302 if (it->second == value) {
303 ++it;
304 } else {
305 it = values->load_value_map.erase(it);
306 }
307 }
308 return true;
309}
310
Vladimir Markob19955d2014-07-29 12:04:10 +0100311template <typename K>
312void LocalValueNumbering::CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
313 const ScopedArenaSafeMap<K, AliasingValues>& src) {
314 // We need each new AliasingValues (or rather its map members) to be constructed
315 // with our allocator, rather than the allocator of the source.
316 for (const auto& entry : src) {
317 auto it = dest->PutBefore(dest->end(), entry.first, AliasingValues(this));
318 it->second = entry.second; // Map assignments preserve current allocator.
319 }
320}
321
322LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id,
323 ScopedArenaAllocator* allocator)
Vladimir Marko95a05972014-05-30 10:01:32 +0100324 : gvn_(gvn),
325 id_(id),
Vladimir Markob19955d2014-07-29 12:04:10 +0100326 sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
327 sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
328 sfield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
329 non_aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
330 aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
331 non_aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
332 aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
Vladimir Marko95a05972014-05-30 10:01:32 +0100333 global_memory_version_(0u),
Vladimir Markob19955d2014-07-29 12:04:10 +0100334 non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
335 escaped_refs_(std::less<uint16_t>(), allocator->Adapter()),
336 escaped_ifield_clobber_set_(EscapedIFieldClobberKeyComparator(), allocator->Adapter()),
337 escaped_array_clobber_set_(EscapedArrayClobberKeyComparator(), allocator->Adapter()),
338 range_checked_(RangeCheckKeyComparator() , allocator->Adapter()),
339 null_checked_(std::less<uint16_t>(), allocator->Adapter()),
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800340 div_zero_checked_(std::less<uint16_t>(), allocator->Adapter()),
Vladimir Markob19955d2014-07-29 12:04:10 +0100341 merge_names_(allocator->Adapter()),
342 merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), allocator->Adapter()),
Vladimir Marko95a05972014-05-30 10:01:32 +0100343 merge_new_memory_version_(kNoValue) {
Vladimir Marko321b9872014-11-24 16:33:51 +0000344 std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_), 0u);
345 std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100346}
347
348bool LocalValueNumbering::Equals(const LocalValueNumbering& other) const {
349 DCHECK(gvn_ == other.gvn_);
350 // Compare the maps/sets and memory versions.
351 return sreg_value_map_ == other.sreg_value_map_ &&
352 sreg_wide_value_map_ == other.sreg_wide_value_map_ &&
353 sfield_value_map_ == other.sfield_value_map_ &&
354 non_aliasing_ifield_value_map_ == other.non_aliasing_ifield_value_map_ &&
355 aliasing_ifield_value_map_ == other.aliasing_ifield_value_map_ &&
356 non_aliasing_array_value_map_ == other.non_aliasing_array_value_map_ &&
357 aliasing_array_value_map_ == other.aliasing_array_value_map_ &&
358 SameMemoryVersion(other) &&
359 non_aliasing_refs_ == other.non_aliasing_refs_ &&
360 escaped_refs_ == other.escaped_refs_ &&
361 escaped_ifield_clobber_set_ == other.escaped_ifield_clobber_set_ &&
362 escaped_array_clobber_set_ == other.escaped_array_clobber_set_ &&
363 range_checked_ == other.range_checked_ &&
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800364 null_checked_ == other.null_checked_ &&
365 div_zero_checked_ == other.div_zero_checked_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100366}
367
368void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType merge_type) {
Vladimir Markob19955d2014-07-29 12:04:10 +0100369 CopyLiveSregValues(&sreg_value_map_, other.sreg_value_map_);
370 CopyLiveSregValues(&sreg_wide_value_map_, other.sreg_wide_value_map_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100371
372 if (merge_type == kReturnMerge) {
373 // RETURN or PHI+RETURN. We need only sreg value maps.
374 return;
375 }
376
377 non_aliasing_ifield_value_map_ = other.non_aliasing_ifield_value_map_;
Vladimir Markob19955d2014-07-29 12:04:10 +0100378 CopyAliasingValuesMap(&non_aliasing_array_value_map_, other.non_aliasing_array_value_map_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100379 non_aliasing_refs_ = other.non_aliasing_refs_;
380 range_checked_ = other.range_checked_;
381 null_checked_ = other.null_checked_;
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800382 div_zero_checked_ = other.div_zero_checked_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100383
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100384 const BasicBlock* pred_bb = gvn_->GetBasicBlock(other.Id());
385 if (GlobalValueNumbering::HasNullCheckLastInsn(pred_bb, Id())) {
386 int s_reg = pred_bb->last_mir_insn->ssa_rep->uses[0];
387 null_checked_.insert(other.GetOperandValue(s_reg));
388 }
389
Vladimir Marko95a05972014-05-30 10:01:32 +0100390 if (merge_type == kCatchMerge) {
391 // Memory is clobbered. Use new memory version and don't merge aliasing locations.
392 global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
Vladimir Marko321b9872014-11-24 16:33:51 +0000393 std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_),
394 global_memory_version_);
395 std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_),
396 global_memory_version_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100397 PruneNonAliasingRefsForCatch();
398 return;
399 }
400
401 DCHECK(merge_type == kNormalMerge);
402 global_memory_version_ = other.global_memory_version_;
Vladimir Marko321b9872014-11-24 16:33:51 +0000403 std::copy_n(other.unresolved_ifield_version_, arraysize(unresolved_sfield_version_),
404 unresolved_ifield_version_);
405 std::copy_n(other.unresolved_sfield_version_, arraysize(unresolved_ifield_version_),
406 unresolved_sfield_version_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100407 sfield_value_map_ = other.sfield_value_map_;
Vladimir Markob19955d2014-07-29 12:04:10 +0100408 CopyAliasingValuesMap(&aliasing_ifield_value_map_, other.aliasing_ifield_value_map_);
409 CopyAliasingValuesMap(&aliasing_array_value_map_, other.aliasing_array_value_map_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100410 escaped_refs_ = other.escaped_refs_;
411 escaped_ifield_clobber_set_ = other.escaped_ifield_clobber_set_;
412 escaped_array_clobber_set_ = other.escaped_array_clobber_set_;
413}
414
415bool LocalValueNumbering::SameMemoryVersion(const LocalValueNumbering& other) const {
416 return
417 global_memory_version_ == other.global_memory_version_ &&
Vladimir Marko321b9872014-11-24 16:33:51 +0000418 std::equal(unresolved_ifield_version_,
419 unresolved_ifield_version_ + arraysize(unresolved_ifield_version_),
Vladimir Marko95a05972014-05-30 10:01:32 +0100420 other.unresolved_ifield_version_) &&
Vladimir Marko321b9872014-11-24 16:33:51 +0000421 std::equal(unresolved_sfield_version_,
422 unresolved_sfield_version_ + arraysize(unresolved_sfield_version_),
Vladimir Marko95a05972014-05-30 10:01:32 +0100423 other.unresolved_sfield_version_);
424}
425
426uint16_t LocalValueNumbering::NewMemoryVersion(uint16_t* new_version) {
427 if (*new_version == kNoValue) {
428 *new_version = gvn_->LookupValue(kMergeBlockMemoryVersionBumpOp, 0u, 0u, id_);
429 }
430 return *new_version;
431}
432
433void LocalValueNumbering::MergeMemoryVersions(bool clobbered_catch) {
434 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
435 const LocalValueNumbering* cmp = gvn_->merge_lvns_[0];
436 // Check if the global version has changed.
437 bool new_global_version = clobbered_catch;
438 if (!new_global_version) {
439 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
440 if (lvn->global_memory_version_ != cmp->global_memory_version_) {
441 // Use a new version for everything.
442 new_global_version = true;
443 break;
444 }
445 }
446 }
447 if (new_global_version) {
448 global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
Vladimir Marko321b9872014-11-24 16:33:51 +0000449 std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_),
450 merge_new_memory_version_);
451 std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_),
452 merge_new_memory_version_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100453 } else {
454 // Initialize with a copy of memory versions from the comparison LVN.
455 global_memory_version_ = cmp->global_memory_version_;
Vladimir Marko321b9872014-11-24 16:33:51 +0000456 std::copy_n(cmp->unresolved_ifield_version_, arraysize(unresolved_sfield_version_),
457 unresolved_ifield_version_);
458 std::copy_n(cmp->unresolved_sfield_version_, arraysize(unresolved_ifield_version_),
459 unresolved_sfield_version_);
Vladimir Marko95a05972014-05-30 10:01:32 +0100460 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
461 if (lvn == cmp) {
462 continue;
463 }
Vladimir Marko321b9872014-11-24 16:33:51 +0000464 for (size_t i = 0; i != kDexMemAccessTypeCount; ++i) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100465 if (lvn->unresolved_ifield_version_[i] != cmp->unresolved_ifield_version_[i]) {
466 unresolved_ifield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
467 }
468 if (lvn->unresolved_sfield_version_[i] != cmp->unresolved_sfield_version_[i]) {
469 unresolved_sfield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
470 }
471 }
472 }
473 }
474}
475
476void LocalValueNumbering::PruneNonAliasingRefsForCatch() {
477 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
478 const BasicBlock* bb = gvn_->GetBasicBlock(lvn->Id());
Vladimir Marko11ca6122014-07-17 20:50:07 +0100479 if (UNLIKELY(bb->taken == id_) || UNLIKELY(bb->fall_through == id_)) {
480 // Non-exceptional path to a catch handler means that the catch block was actually
481 // empty and all exceptional paths lead to the shared path after that empty block.
482 continue;
483 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100484 DCHECK_EQ(bb->taken, kNullBlock);
485 DCHECK_NE(bb->fall_through, kNullBlock);
486 const BasicBlock* fall_through_bb = gvn_->GetBasicBlock(bb->fall_through);
487 const MIR* mir = fall_through_bb->first_mir_insn;
488 DCHECK(mir != nullptr);
489 // Only INVOKEs can leak and clobber non-aliasing references if they throw.
Jean Christophe Beylerfb0ea2d2014-07-29 13:20:42 -0700490 if ((mir->dalvikInsn.FlagsOf() & Instruction::kInvoke) != 0) {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100491 HandleInvokeArgs(mir, lvn);
Vladimir Marko95a05972014-05-30 10:01:32 +0100492 }
493 }
494}
495
496
497template <typename Set, Set LocalValueNumbering::* set_ptr>
498void LocalValueNumbering::IntersectSets() {
499 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
500
501 // Find the LVN with the least entries in the set.
502 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
503 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
504 if ((lvn->*set_ptr).size() < (least_entries_lvn->*set_ptr).size()) {
505 least_entries_lvn = lvn;
506 }
507 }
508
509 // For each key check if it's in all the LVNs.
510 for (const auto& key : least_entries_lvn->*set_ptr) {
511 bool checked = true;
512 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
513 if (lvn != least_entries_lvn && (lvn->*set_ptr).count(key) == 0u) {
514 checked = false;
515 break;
516 }
517 }
518 if (checked) {
519 (this->*set_ptr).emplace_hint((this->*set_ptr).end(), key);
520 }
521 }
522}
523
Vladimir Markob19955d2014-07-29 12:04:10 +0100524void LocalValueNumbering::CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src) {
525 auto dest_end = dest->end();
526 ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
527 DCHECK(live_in_v != nullptr);
528 for (const auto& entry : src) {
529 bool live = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
530 if (live) {
531 dest->PutBefore(dest_end, entry.first, entry.second);
532 }
533 }
534}
535
536template <LocalValueNumbering::SregValueMap LocalValueNumbering::* map_ptr>
537void LocalValueNumbering::IntersectSregValueMaps() {
Vladimir Marko95a05972014-05-30 10:01:32 +0100538 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
539
540 // Find the LVN with the least entries in the set.
541 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
542 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
543 if ((lvn->*map_ptr).size() < (least_entries_lvn->*map_ptr).size()) {
544 least_entries_lvn = lvn;
545 }
546 }
547
548 // For each key check if it's in all the LVNs.
Vladimir Markob19955d2014-07-29 12:04:10 +0100549 ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
550 DCHECK(live_in_v != nullptr);
Vladimir Marko95a05972014-05-30 10:01:32 +0100551 for (const auto& entry : least_entries_lvn->*map_ptr) {
Vladimir Markob19955d2014-07-29 12:04:10 +0100552 bool live_and_same = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
553 if (live_and_same) {
554 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
555 if (lvn != least_entries_lvn) {
556 auto it = (lvn->*map_ptr).find(entry.first);
557 if (it == (lvn->*map_ptr).end() || !(it->second == entry.second)) {
558 live_and_same = false;
559 break;
560 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100561 }
562 }
563 }
Vladimir Markob19955d2014-07-29 12:04:10 +0100564 if (live_and_same) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100565 (this->*map_ptr).PutBefore((this->*map_ptr).end(), entry.first, entry.second);
566 }
567 }
568}
569
570// Intersect maps as sets. The value type must be equality-comparable.
571template <typename Map>
572void LocalValueNumbering::InPlaceIntersectMaps(Map* work_map, const Map& other_map) {
573 auto work_it = work_map->begin(), work_end = work_map->end();
574 auto cmp = work_map->value_comp();
575 for (const auto& entry : other_map) {
576 while (work_it != work_end &&
577 (cmp(*work_it, entry) ||
578 (!cmp(entry, *work_it) && !(work_it->second == entry.second)))) {
579 work_it = work_map->erase(work_it);
580 }
Vladimir Marko55fff042014-07-10 12:42:52 +0100581 if (work_it == work_end) {
582 return;
583 }
584 ++work_it;
Vladimir Marko95a05972014-05-30 10:01:32 +0100585 }
586}
587
588template <typename Set, Set LocalValueNumbering::*set_ptr, void (LocalValueNumbering::*MergeFn)(
589 const typename Set::value_type& entry, typename Set::iterator hint)>
590void LocalValueNumbering::MergeSets() {
591 auto cmp = (this->*set_ptr).value_comp();
592 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
593 auto my_it = (this->*set_ptr).begin(), my_end = (this->*set_ptr).end();
594 for (const auto& entry : lvn->*set_ptr) {
595 while (my_it != my_end && cmp(*my_it, entry)) {
596 ++my_it;
597 }
598 if (my_it != my_end && !cmp(entry, *my_it)) {
599 // Already handled.
600 ++my_it;
601 } else {
602 // Merge values for this field_id.
603 (this->*MergeFn)(entry, my_it); // my_it remains valid across inserts to std::set/SafeMap.
604 }
605 }
606 }
607}
608
609void LocalValueNumbering::IntersectAliasingValueLocations(AliasingValues* work_values,
610 const AliasingValues* values) {
611 auto cmp = work_values->load_value_map.key_comp();
612 auto work_it = work_values->load_value_map.begin(), work_end = work_values->load_value_map.end();
613 auto store_it = values->store_loc_set.begin(), store_end = values->store_loc_set.end();
614 auto load_it = values->load_value_map.begin(), load_end = values->load_value_map.end();
615 while (store_it != store_end || load_it != load_end) {
616 uint16_t loc;
617 if (store_it != store_end && (load_it == load_end || *store_it < load_it->first)) {
618 loc = *store_it;
619 ++store_it;
620 } else {
621 loc = load_it->first;
622 ++load_it;
623 DCHECK(store_it == store_end || cmp(loc, *store_it));
624 }
625 while (work_it != work_end && cmp(work_it->first, loc)) {
626 work_it = work_values->load_value_map.erase(work_it);
627 }
628 if (work_it != work_end && !cmp(loc, work_it->first)) {
629 // The location matches, keep it.
630 ++work_it;
631 }
632 }
633 while (work_it != work_end) {
634 work_it = work_values->load_value_map.erase(work_it);
635 }
636}
637
638void LocalValueNumbering::MergeEscapedRefs(const ValueNameSet::value_type& entry,
639 ValueNameSet::iterator hint) {
640 // See if the ref is either escaped or non-aliasing in each predecessor.
641 bool is_escaped = true;
642 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
643 if (lvn->non_aliasing_refs_.count(entry) == 0u &&
644 lvn->escaped_refs_.count(entry) == 0u) {
645 is_escaped = false;
646 break;
647 }
648 }
649 if (is_escaped) {
650 escaped_refs_.emplace_hint(hint, entry);
651 }
652}
653
654void LocalValueNumbering::MergeEscapedIFieldTypeClobberSets(
655 const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
656 // Insert only type-clobber entries (field_id == kNoValue) of escaped refs.
657 if (entry.field_id == kNoValue && escaped_refs_.count(entry.base) != 0u) {
658 escaped_ifield_clobber_set_.emplace_hint(hint, entry);
659 }
660}
661
662void LocalValueNumbering::MergeEscapedIFieldClobberSets(
663 const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
664 // Insert only those entries of escaped refs that are not overridden by a type clobber.
665 if (!(hint == escaped_ifield_clobber_set_.end() &&
666 hint->base == entry.base && hint->type == entry.type) &&
667 escaped_refs_.count(entry.base) != 0u) {
668 escaped_ifield_clobber_set_.emplace_hint(hint, entry);
669 }
670}
671
672void LocalValueNumbering::MergeEscapedArrayClobberSets(
673 const EscapedArrayClobberSet::value_type& entry, EscapedArrayClobberSet::iterator hint) {
674 if (escaped_refs_.count(entry.base) != 0u) {
675 escaped_array_clobber_set_.emplace_hint(hint, entry);
676 }
677}
678
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100679void LocalValueNumbering::MergeNullChecked() {
680 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
681
682 // Find the LVN with the least entries in the set.
683 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
684 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
685 if (lvn->null_checked_.size() < least_entries_lvn->null_checked_.size()) {
686 least_entries_lvn = lvn;
687 }
688 }
689
690 // For each null-checked value name check if it's null-checked in all the LVNs.
691 for (const auto& value_name : least_entries_lvn->null_checked_) {
692 // Merge null_checked_ for this ref.
693 merge_names_.clear();
694 merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
695 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
696 null_checked_.insert(null_checked_.end(), value_name);
697 }
698 }
699
700 // Now check if the least_entries_lvn has a null-check as the last insn.
701 const BasicBlock* least_entries_bb = gvn_->GetBasicBlock(least_entries_lvn->Id());
702 if (gvn_->HasNullCheckLastInsn(least_entries_bb, id_)) {
703 int s_reg = least_entries_bb->last_mir_insn->ssa_rep->uses[0];
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100704 uint32_t value_name = least_entries_lvn->GetOperandValue(s_reg);
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100705 merge_names_.clear();
706 merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
707 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
708 null_checked_.insert(value_name);
709 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100710 }
711}
712
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800713void LocalValueNumbering::MergeDivZeroChecked() {
714 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
715
716 // Find the LVN with the least entries in the set.
717 const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
718 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
719 if (lvn->div_zero_checked_.size() < least_entries_lvn->div_zero_checked_.size()) {
720 least_entries_lvn = lvn;
721 }
722 }
723
724 // For each div-zero value name check if it's div-zero checked in all the LVNs.
725 for (const auto& value_name : least_entries_lvn->div_zero_checked_) {
726 // Merge null_checked_ for this ref.
727 merge_names_.clear();
728 merge_names_.resize(gvn_->merge_lvns_.size(), value_name);
729 if (gvn_->DivZeroCheckedInAllPredecessors(merge_names_)) {
730 div_zero_checked_.insert(div_zero_checked_.end(), value_name);
731 }
732 }
733}
734
Vladimir Marko95a05972014-05-30 10:01:32 +0100735void LocalValueNumbering::MergeSFieldValues(const SFieldToValueMap::value_type& entry,
736 SFieldToValueMap::iterator hint) {
737 uint16_t field_id = entry.first;
738 merge_names_.clear();
739 uint16_t value_name = kNoValue;
740 bool same_values = true;
741 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
742 // Get the value name as in HandleSGet() but don't modify *lvn.
743 auto it = lvn->sfield_value_map_.find(field_id);
744 if (it != lvn->sfield_value_map_.end()) {
745 value_name = it->second;
746 } else {
Vladimir Markoaf6925b2014-10-31 16:37:32 +0000747 uint16_t type = gvn_->GetSFieldType(field_id);
Vladimir Marko95a05972014-05-30 10:01:32 +0100748 value_name = gvn_->LookupValue(kResolvedSFieldOp, field_id,
749 lvn->unresolved_sfield_version_[type],
750 lvn->global_memory_version_);
751 }
752
753 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
754 merge_names_.push_back(value_name);
755 }
756 if (same_values) {
757 // value_name already contains the result.
758 } else {
759 auto lb = merge_map_.lower_bound(merge_names_);
760 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
761 value_name = lb->second;
762 } else {
763 value_name = gvn_->LookupValue(kMergeBlockSFieldVersionBumpOp, field_id, id_, kNoValue);
764 merge_map_.PutBefore(lb, merge_names_, value_name);
765 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
766 null_checked_.insert(value_name);
767 }
768 }
769 }
770 sfield_value_map_.PutBefore(hint, field_id, value_name);
771}
772
773void LocalValueNumbering::MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type& entry,
774 IFieldLocToValueMap::iterator hint) {
775 uint16_t field_loc = entry.first;
776 merge_names_.clear();
777 uint16_t value_name = kNoValue;
778 bool same_values = true;
779 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
780 // Get the value name as in HandleIGet() but don't modify *lvn.
781 auto it = lvn->non_aliasing_ifield_value_map_.find(field_loc);
782 if (it != lvn->non_aliasing_ifield_value_map_.end()) {
783 value_name = it->second;
784 } else {
785 value_name = gvn_->LookupValue(kNonAliasingIFieldInitialOp, field_loc, kNoValue, kNoValue);
786 }
787
788 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
789 merge_names_.push_back(value_name);
790 }
791 if (same_values) {
792 // value_name already contains the result.
793 } else {
794 auto lb = merge_map_.lower_bound(merge_names_);
795 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
796 value_name = lb->second;
797 } else {
798 value_name = gvn_->LookupValue(kMergeBlockNonAliasingIFieldVersionBumpOp, field_loc,
799 id_, kNoValue);
800 merge_map_.PutBefore(lb, merge_names_, value_name);
801 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
802 null_checked_.insert(value_name);
803 }
804 }
805 }
806 non_aliasing_ifield_value_map_.PutBefore(hint, field_loc, value_name);
807}
808
809template <typename Map, Map LocalValueNumbering::*map_ptr, typename Versions>
810void LocalValueNumbering::MergeAliasingValues(const typename Map::value_type& entry,
811 typename Map::iterator hint) {
812 const typename Map::key_type& key = entry.first;
813
Vladimir Markob19955d2014-07-29 12:04:10 +0100814 auto it = (this->*map_ptr).PutBefore(hint, key, AliasingValues(this));
Vladimir Marko95a05972014-05-30 10:01:32 +0100815 AliasingValues* my_values = &it->second;
816
817 const AliasingValues* cmp_values = nullptr;
818 bool same_version = !Versions::HasNewBaseVersion(gvn_, this, key);
819 uint16_t load_memory_version_for_same_version = kNoValue;
820 if (same_version) {
821 // Find the first non-null values.
822 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800823 auto value = (lvn->*map_ptr).find(key);
824 if (value != (lvn->*map_ptr).end()) {
825 cmp_values = &value->second;
Vladimir Marko95a05972014-05-30 10:01:32 +0100826 break;
827 }
828 }
829 DCHECK(cmp_values != nullptr); // There must be at least one non-null values.
830
831 // Check if we have identical memory versions, i.e. the global memory version, unresolved
832 // field version and the values' memory_version_before_stores, last_stored_value
833 // and store_loc_set are identical.
834 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800835 auto value = (lvn->*map_ptr).find(key);
836 if (value == (lvn->*map_ptr).end()) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100837 if (cmp_values->memory_version_before_stores != kNoValue) {
838 same_version = false;
839 break;
840 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800841 } else if (cmp_values->last_stored_value != value->second.last_stored_value ||
842 cmp_values->memory_version_before_stores != value->second.memory_version_before_stores ||
843 cmp_values->store_loc_set != value->second.store_loc_set) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100844 same_version = false;
845 break;
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800846 } else if (value->second.last_load_memory_version != kNoValue) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100847 DCHECK(load_memory_version_for_same_version == kNoValue ||
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800848 load_memory_version_for_same_version == value->second.last_load_memory_version);
849 load_memory_version_for_same_version = value->second.last_load_memory_version;
Vladimir Marko95a05972014-05-30 10:01:32 +0100850 }
851 }
852 }
853
854 if (same_version) {
855 // Copy the identical values.
856 my_values->memory_version_before_stores = cmp_values->memory_version_before_stores;
857 my_values->last_stored_value = cmp_values->last_stored_value;
858 my_values->store_loc_set = cmp_values->store_loc_set;
859 my_values->last_load_memory_version = load_memory_version_for_same_version;
860 // Merge load values seen in all incoming arcs (i.e. an intersection).
861 if (!cmp_values->load_value_map.empty()) {
862 my_values->load_value_map = cmp_values->load_value_map;
863 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800864 auto value = (lvn->*map_ptr).find(key);
865 if (value == (lvn->*map_ptr).end() || value->second.load_value_map.empty()) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100866 my_values->load_value_map.clear();
867 break;
868 }
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800869 InPlaceIntersectMaps(&my_values->load_value_map, value->second.load_value_map);
Vladimir Marko95a05972014-05-30 10:01:32 +0100870 if (my_values->load_value_map.empty()) {
871 break;
872 }
873 }
874 }
875 } else {
876 // Bump version number for the merge.
877 my_values->memory_version_before_stores = my_values->last_load_memory_version =
878 Versions::LookupMergeBlockValue(gvn_, id_, key);
879
880 // Calculate the locations that have been either read from or written to in each incoming LVN.
881 bool first_lvn = true;
882 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800883 auto value = (lvn->*map_ptr).find(key);
884 if (value == (lvn->*map_ptr).end()) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100885 my_values->load_value_map.clear();
886 break;
887 }
888 if (first_lvn) {
889 first_lvn = false;
890 // Copy the first LVN's locations. Values will be overwritten later.
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800891 my_values->load_value_map = value->second.load_value_map;
892 for (uint16_t location : value->second.store_loc_set) {
Vladimir Marko95a05972014-05-30 10:01:32 +0100893 my_values->load_value_map.Put(location, 0u);
894 }
895 } else {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800896 IntersectAliasingValueLocations(my_values, &value->second);
Vladimir Marko95a05972014-05-30 10:01:32 +0100897 }
898 }
899 // Calculate merged values for the intersection.
900 for (auto& load_value_entry : my_values->load_value_map) {
901 uint16_t location = load_value_entry.first;
Vladimir Marko95a05972014-05-30 10:01:32 +0100902 merge_names_.clear();
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000903 uint16_t value_name = kNoValue;
904 bool same_values = true;
Vladimir Marko95a05972014-05-30 10:01:32 +0100905 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
906 value_name = Versions::LookupMergeValue(gvn_, lvn, key, location);
907 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
908 merge_names_.push_back(value_name);
909 }
910 if (same_values) {
911 // value_name already contains the result.
912 } else {
913 auto lb = merge_map_.lower_bound(merge_names_);
914 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
915 value_name = lb->second;
916 } else {
917 // NOTE: In addition to the key and id_ which don't change on an LVN recalculation
918 // during GVN, we also add location which can actually change on recalculation, so the
919 // value_name below may change. This could lead to an infinite loop if the location
920 // value name always changed when the refereced value name changes. However, given that
921 // we assign unique value names for other merges, such as Phis, such a dependency is
922 // not possible in a well-formed SSA graph.
923 value_name = Versions::LookupMergeLocationValue(gvn_, id_, key, location);
924 merge_map_.PutBefore(lb, merge_names_, value_name);
925 if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
926 null_checked_.insert(value_name);
927 }
928 }
929 }
930 load_value_entry.second = value_name;
931 }
932 }
933}
934
935void LocalValueNumbering::Merge(MergeType merge_type) {
936 DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
937
Vladimir Marko7a01dc22015-01-02 17:00:44 +0000938 // Always reserve space in merge_names_. Even if we don't use it in Merge() we may need it
939 // in GetStartingVregValueNumberImpl() when the merge_names_'s allocator is not the top.
940 merge_names_.reserve(gvn_->merge_lvns_.size());
941
Vladimir Markob19955d2014-07-29 12:04:10 +0100942 IntersectSregValueMaps<&LocalValueNumbering::sreg_value_map_>();
943 IntersectSregValueMaps<&LocalValueNumbering::sreg_wide_value_map_>();
Vladimir Marko95a05972014-05-30 10:01:32 +0100944 if (merge_type == kReturnMerge) {
945 // RETURN or PHI+RETURN. We need only sreg value maps.
946 return;
947 }
948
949 MergeMemoryVersions(merge_type == kCatchMerge);
950
951 // Merge non-aliasing maps/sets.
Vladimir Marko95a05972014-05-30 10:01:32 +0100952 IntersectSets<ValueNameSet, &LocalValueNumbering::non_aliasing_refs_>();
Vladimir Marko55fff042014-07-10 12:42:52 +0100953 if (!non_aliasing_refs_.empty() && merge_type == kCatchMerge) {
954 PruneNonAliasingRefsForCatch();
955 }
956 if (!non_aliasing_refs_.empty()) {
957 MergeSets<IFieldLocToValueMap, &LocalValueNumbering::non_aliasing_ifield_value_map_,
958 &LocalValueNumbering::MergeNonAliasingIFieldValues>();
959 MergeSets<NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
960 &LocalValueNumbering::MergeAliasingValues<
961 NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
962 NonAliasingArrayVersions>>();
963 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100964
965 // We won't do anything complicated for range checks, just calculate the intersection.
966 IntersectSets<RangeCheckSet, &LocalValueNumbering::range_checked_>();
967
968 // Merge null_checked_. We may later insert more, such as merged object field values.
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100969 MergeNullChecked();
Vladimir Marko95a05972014-05-30 10:01:32 +0100970
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800971 // Now merge the div_zero_checked_.
972 MergeDivZeroChecked();
973
Vladimir Marko95a05972014-05-30 10:01:32 +0100974 if (merge_type == kCatchMerge) {
975 // Memory is clobbered. New memory version already created, don't merge aliasing locations.
Vladimir Marko95a05972014-05-30 10:01:32 +0100976 return;
977 }
978
979 DCHECK(merge_type == kNormalMerge);
980
981 // Merge escaped refs and clobber sets.
982 MergeSets<ValueNameSet, &LocalValueNumbering::escaped_refs_,
983 &LocalValueNumbering::MergeEscapedRefs>();
984 if (!escaped_refs_.empty()) {
985 MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
986 &LocalValueNumbering::MergeEscapedIFieldTypeClobberSets>();
987 MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
988 &LocalValueNumbering::MergeEscapedIFieldClobberSets>();
989 MergeSets<EscapedArrayClobberSet, &LocalValueNumbering::escaped_array_clobber_set_,
990 &LocalValueNumbering::MergeEscapedArrayClobberSets>();
991 }
992
993 MergeSets<SFieldToValueMap, &LocalValueNumbering::sfield_value_map_,
994 &LocalValueNumbering::MergeSFieldValues>();
995 MergeSets<AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
996 &LocalValueNumbering::MergeAliasingValues<
997 AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
998 AliasingIFieldVersions>>();
999 MergeSets<AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
1000 &LocalValueNumbering::MergeAliasingValues<
1001 AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
1002 AliasingArrayVersions>>();
Vladimir Markof59f18b2014-02-17 15:53:57 +00001003}
1004
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001005void LocalValueNumbering::PrepareEntryBlock() {
1006 uint32_t vreg = gvn_->GetMirGraph()->GetFirstInVR();
1007 CompilationUnit* cu = gvn_->GetCompilationUnit();
1008 const char* shorty = cu->shorty;
1009 ++shorty; // Skip return value.
1010 if ((cu->access_flags & kAccStatic) == 0) {
1011 // If non-static method, mark "this" as non-null
1012 uint16_t value_name = GetOperandValue(vreg);
1013 ++vreg;
1014 null_checked_.insert(value_name);
1015 }
1016 for ( ; *shorty != 0; ++shorty, ++vreg) {
1017 if (*shorty == 'J' || *shorty == 'D') {
1018 uint16_t value_name = GetOperandValueWide(vreg);
1019 SetOperandValueWide(vreg, value_name);
1020 ++vreg;
1021 }
1022 }
1023}
1024
Vladimir Markof59f18b2014-02-17 15:53:57 +00001025uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
1026 uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001027 DCHECK(null_checked_.find(res) == null_checked_.end());
1028 null_checked_.insert(res);
1029 non_aliasing_refs_.insert(res);
1030 return res;
1031}
1032
Vladimir Marko95a05972014-05-30 10:01:32 +01001033bool LocalValueNumbering::IsNonAliasing(uint16_t reg) const {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001034 return non_aliasing_refs_.find(reg) != non_aliasing_refs_.end();
Vladimir Markof59f18b2014-02-17 15:53:57 +00001035}
1036
Vladimir Marko95a05972014-05-30 10:01:32 +01001037bool LocalValueNumbering::IsNonAliasingIField(uint16_t reg, uint16_t field_id,
1038 uint16_t type) const {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001039 if (IsNonAliasing(reg)) {
1040 return true;
1041 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001042 if (escaped_refs_.find(reg) == escaped_refs_.end()) {
1043 return false;
1044 }
1045 // Check for IPUTs to unresolved fields.
1046 EscapedIFieldClobberKey key1 = { reg, type, kNoValue };
1047 if (escaped_ifield_clobber_set_.find(key1) != escaped_ifield_clobber_set_.end()) {
1048 return false;
1049 }
1050 // Check for aliased IPUTs to the same field.
1051 EscapedIFieldClobberKey key2 = { reg, type, field_id };
1052 return escaped_ifield_clobber_set_.find(key2) == escaped_ifield_clobber_set_.end();
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001053}
1054
Vladimir Marko95a05972014-05-30 10:01:32 +01001055bool LocalValueNumbering::IsNonAliasingArray(uint16_t reg, uint16_t type) const {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001056 if (IsNonAliasing(reg)) {
1057 return true;
1058 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001059 if (escaped_refs_.count(reg) == 0u) {
1060 return false;
1061 }
1062 // Check for aliased APUTs.
1063 EscapedArrayClobberKey key = { reg, type };
1064 return escaped_array_clobber_set_.find(key) == escaped_array_clobber_set_.end();
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001065}
1066
Vladimir Markof59f18b2014-02-17 15:53:57 +00001067void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001068 auto lb = null_checked_.lower_bound(reg);
1069 if (lb != null_checked_.end() && *lb == reg) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001070 if (LIKELY(gvn_->CanModify())) {
1071 if (gvn_->GetCompilationUnit()->verbose) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001072 LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset;
1073 }
1074 mir->optimization_flags |= MIR_IGNORE_NULL_CHECK;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001075 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001076 } else {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001077 null_checked_.insert(lb, reg);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001078 }
1079}
1080
1081void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001082 RangeCheckKey key = { array, index };
1083 auto lb = range_checked_.lower_bound(key);
1084 if (lb != range_checked_.end() && !RangeCheckKeyComparator()(key, *lb)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001085 if (LIKELY(gvn_->CanModify())) {
1086 if (gvn_->GetCompilationUnit()->verbose) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001087 LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
1088 }
1089 mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001090 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001091 } else {
1092 // Mark range check completed.
1093 range_checked_.insert(lb, key);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001094 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001095}
1096
Razvan A Lupusorue0951142014-11-14 14:36:55 -08001097void LocalValueNumbering::HandleDivZeroCheck(MIR* mir, uint16_t reg) {
1098 auto lb = div_zero_checked_.lower_bound(reg);
1099 if (lb != div_zero_checked_.end() && *lb == reg) {
1100 if (LIKELY(gvn_->CanModify())) {
1101 if (gvn_->GetCompilationUnit()->verbose) {
1102 LOG(INFO) << "Removing div zero check for 0x" << std::hex << mir->offset;
1103 }
1104 mir->optimization_flags |= MIR_IGNORE_DIV_ZERO_CHECK;
1105 }
1106 } else {
1107 div_zero_checked_.insert(lb, reg);
1108 }
1109}
1110
Vladimir Markof59f18b2014-02-17 15:53:57 +00001111void LocalValueNumbering::HandlePutObject(MIR* mir) {
1112 // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
1113 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001114 HandleEscapingRef(base);
Vladimir Marko743b98c2014-11-24 19:45:41 +00001115 if (gvn_->CanModify() && null_checked_.count(base) != 0u) {
1116 if (gvn_->GetCompilationUnit()->verbose) {
1117 LOG(INFO) << "Removing GC card mark value null check for 0x" << std::hex << mir->offset;
1118 }
1119 mir->optimization_flags |= MIR_STORE_NON_NULL_VALUE;
1120 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001121}
1122
1123void LocalValueNumbering::HandleEscapingRef(uint16_t base) {
1124 auto it = non_aliasing_refs_.find(base);
1125 if (it != non_aliasing_refs_.end()) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001126 non_aliasing_refs_.erase(it);
Vladimir Marko95a05972014-05-30 10:01:32 +01001127 escaped_refs_.insert(base);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001128 }
1129}
1130
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001131void LocalValueNumbering::HandleInvokeArgs(const MIR* mir, const LocalValueNumbering* mir_lvn) {
1132 const int32_t* uses = mir->ssa_rep->uses;
1133 const int32_t* uses_end = uses + mir->ssa_rep->num_uses;
1134 while (uses != uses_end) {
1135 uint16_t sreg = *uses;
1136 ++uses;
1137 // Avoid LookupValue() so that we don't store new values in the global value map.
1138 auto local_it = mir_lvn->sreg_value_map_.find(sreg);
1139 if (local_it != mir_lvn->sreg_value_map_.end()) {
1140 non_aliasing_refs_.erase(local_it->second);
1141 } else {
1142 uint16_t value_name = gvn_->FindValue(kNoValue, sreg, kNoValue, kNoValue);
1143 if (value_name != kNoValue) {
1144 non_aliasing_refs_.erase(value_name);
1145 }
1146 }
1147 }
1148}
1149
Vladimir Marko95a05972014-05-30 10:01:32 +01001150uint16_t LocalValueNumbering::HandlePhi(MIR* mir) {
1151 if (gvn_->merge_lvns_.empty()) {
1152 // Running LVN without a full GVN?
1153 return kNoValue;
1154 }
Vladimir Markoa5e69e82015-04-24 19:03:51 +01001155 // Determine if this Phi is merging wide regs.
1156 RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir);
1157 if (raw_dest.high_word) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001158 // This is the high part of a wide reg. Ignore the Phi.
1159 return kNoValue;
1160 }
Vladimir Markoa5e69e82015-04-24 19:03:51 +01001161 bool wide = raw_dest.wide;
Vladimir Marko95a05972014-05-30 10:01:32 +01001162 // Iterate over *merge_lvns_ and skip incoming sregs for BBs without associated LVN.
Vladimir Marko95a05972014-05-30 10:01:32 +01001163 merge_names_.clear();
Vladimir Marko7a01dc22015-01-02 17:00:44 +00001164 uint16_t value_name = kNoValue;
Vladimir Marko95a05972014-05-30 10:01:32 +01001165 bool same_values = true;
Vladimir Markoa5e69e82015-04-24 19:03:51 +01001166 BasicBlockId* incoming = mir->meta.phi_incoming;
1167 int32_t* uses = mir->ssa_rep->uses;
1168 int16_t pos = 0;
Vladimir Marko95a05972014-05-30 10:01:32 +01001169 for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
1170 DCHECK_LT(pos, mir->ssa_rep->num_uses);
1171 while (incoming[pos] != lvn->Id()) {
1172 ++pos;
1173 DCHECK_LT(pos, mir->ssa_rep->num_uses);
1174 }
1175 int s_reg = uses[pos];
1176 ++pos;
1177 value_name = wide ? lvn->GetOperandValueWide(s_reg) : lvn->GetOperandValue(s_reg);
1178
1179 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
1180 merge_names_.push_back(value_name);
1181 }
1182 if (same_values) {
1183 // value_name already contains the result.
1184 } else {
1185 auto lb = merge_map_.lower_bound(merge_names_);
1186 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
1187 value_name = lb->second;
1188 } else {
1189 value_name = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
1190 merge_map_.PutBefore(lb, merge_names_, value_name);
1191 if (!wide && gvn_->NullCheckedInAllPredecessors(merge_names_)) {
1192 null_checked_.insert(value_name);
1193 }
Razvan A Lupusorue0951142014-11-14 14:36:55 -08001194 if (gvn_->DivZeroCheckedInAllPredecessors(merge_names_)) {
1195 div_zero_checked_.insert(value_name);
1196 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001197 }
1198 }
1199 if (wide) {
1200 SetOperandValueWide(mir->ssa_rep->defs[0], value_name);
1201 } else {
1202 SetOperandValue(mir->ssa_rep->defs[0], value_name);
1203 }
1204 return value_name;
1205}
1206
Vladimir Marko22c7f5b2015-02-18 17:52:39 +00001207uint16_t LocalValueNumbering::HandleConst(MIR* mir, uint32_t value) {
1208 RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir);
1209 uint16_t res;
1210 if (value == 0u && raw_dest.ref) {
1211 res = GlobalValueNumbering::kNullValue;
1212 } else {
1213 Instruction::Code op = raw_dest.fp ? Instruction::CONST_HIGH16 : Instruction::CONST;
1214 res = gvn_->LookupValue(op, Low16Bits(value), High16Bits(value), 0);
1215 }
1216 SetOperandValue(mir->ssa_rep->defs[0], res);
1217 return res;
1218}
1219
1220uint16_t LocalValueNumbering::HandleConstWide(MIR* mir, uint64_t value) {
1221 RegLocation raw_dest = gvn_->GetMirGraph()->GetRawDest(mir);
1222 Instruction::Code op = raw_dest.fp ? Instruction::CONST_HIGH16 : Instruction::CONST;
1223 uint32_t low_word = Low32Bits(value);
1224 uint32_t high_word = High32Bits(value);
1225 uint16_t low_res = gvn_->LookupValue(op, Low16Bits(low_word), High16Bits(low_word), 1);
1226 uint16_t high_res = gvn_->LookupValue(op, Low16Bits(high_word), High16Bits(high_word), 2);
1227 uint16_t res = gvn_->LookupValue(op, low_res, high_res, 3);
1228 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1229 return res;
1230}
1231
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001232uint16_t LocalValueNumbering::HandleAGet(MIR* mir, uint16_t opcode) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001233 uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
1234 HandleNullCheck(mir, array);
1235 uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
1236 HandleRangeCheck(mir, array, index);
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001237 uint16_t type = AGetMemAccessType(static_cast<Instruction::Code>(opcode));
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001238 // Establish value number for loaded register.
1239 uint16_t res;
1240 if (IsNonAliasingArray(array, type)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001241 res = HandleAliasingValuesGet<NonAliasingArrayVersions>(&non_aliasing_array_value_map_,
1242 array, index);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001243 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001244 uint16_t location = gvn_->GetArrayLocation(array, index);
1245 res = HandleAliasingValuesGet<AliasingArrayVersions>(&aliasing_array_value_map_,
1246 type, location);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001247 }
1248 if (opcode == Instruction::AGET_WIDE) {
1249 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1250 } else {
1251 SetOperandValue(mir->ssa_rep->defs[0], res);
1252 }
1253 return res;
1254}
1255
1256void LocalValueNumbering::HandleAPut(MIR* mir, uint16_t opcode) {
1257 int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
1258 int index_idx = array_idx + 1;
1259 uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
1260 HandleNullCheck(mir, array);
1261 uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
1262 HandleRangeCheck(mir, array, index);
1263
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001264 uint16_t type = APutMemAccessType(static_cast<Instruction::Code>(opcode));
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001265 uint16_t value = (opcode == Instruction::APUT_WIDE)
1266 ? GetOperandValueWide(mir->ssa_rep->uses[0])
1267 : GetOperandValue(mir->ssa_rep->uses[0]);
1268 if (IsNonAliasing(array)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001269 bool put_is_live = HandleAliasingValuesPut<NonAliasingArrayVersions>(
1270 &non_aliasing_array_value_map_, array, index, value);
1271 if (!put_is_live) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001272 // This APUT can be eliminated, it stores the same value that's already in the field.
1273 // TODO: Eliminate the APUT.
1274 return;
1275 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001276 } else {
1277 uint16_t location = gvn_->GetArrayLocation(array, index);
1278 bool put_is_live = HandleAliasingValuesPut<AliasingArrayVersions>(
1279 &aliasing_array_value_map_, type, location, value);
1280 if (!put_is_live) {
1281 // This APUT can be eliminated, it stores the same value that's already in the field.
1282 // TODO: Eliminate the APUT.
1283 return;
1284 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001285
Vladimir Marko95a05972014-05-30 10:01:32 +01001286 // Clobber all escaped array refs for this type.
1287 for (uint16_t escaped_array : escaped_refs_) {
1288 EscapedArrayClobberKey clobber_key = { escaped_array, type };
1289 escaped_array_clobber_set_.insert(clobber_key);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001290 }
1291 }
1292}
1293
1294uint16_t LocalValueNumbering::HandleIGet(MIR* mir, uint16_t opcode) {
1295 uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
1296 HandleNullCheck(mir, base);
Vladimir Marko95a05972014-05-30 10:01:32 +01001297 const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001298 uint16_t res;
1299 if (!field_info.IsResolved() || field_info.IsVolatile()) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001300 // Unresolved fields may be volatile, so handle them as such to be safe.
Vladimir Markofa236452014-09-29 17:58:10 +01001301 HandleInvokeOrClInitOrAcquireOp(mir); // Volatile GETs have acquire semantics.
1302 // Volatile fields always get a new memory version; field id is irrelevant.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001303 // Use result s_reg - will be unique.
Vladimir Marko95a05972014-05-30 10:01:32 +01001304 res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001305 } else {
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001306 uint16_t type = IGetMemAccessType(static_cast<Instruction::Code>(opcode));
1307 uint16_t field_id = gvn_->GetIFieldId(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001308 if (IsNonAliasingIField(base, field_id, type)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001309 uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
1310 auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
1311 if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
1312 res = lb->second;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001313 } else {
Vladimir Marko95a05972014-05-30 10:01:32 +01001314 res = gvn_->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
1315 non_aliasing_ifield_value_map_.PutBefore(lb, loc, res);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001316 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001317 } else {
1318 res = HandleAliasingValuesGet<AliasingIFieldVersions>(&aliasing_ifield_value_map_,
1319 field_id, base);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001320 }
1321 }
1322 if (opcode == Instruction::IGET_WIDE) {
1323 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1324 } else {
1325 SetOperandValue(mir->ssa_rep->defs[0], res);
1326 }
1327 return res;
1328}
1329
1330void LocalValueNumbering::HandleIPut(MIR* mir, uint16_t opcode) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001331 int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
1332 uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
1333 HandleNullCheck(mir, base);
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001334 uint16_t type = IPutMemAccessType(static_cast<Instruction::Code>(opcode));
Vladimir Marko95a05972014-05-30 10:01:32 +01001335 const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001336 if (!field_info.IsResolved()) {
1337 // Unresolved fields always alias with everything of the same type.
1338 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1339 unresolved_ifield_version_[type] =
Vladimir Marko95a05972014-05-30 10:01:32 +01001340 gvn_->LookupValue(kUnresolvedIFieldOp, kNoValue, kNoValue, mir->offset);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001341
Vladimir Marko95a05972014-05-30 10:01:32 +01001342 // For simplicity, treat base as escaped now.
1343 HandleEscapingRef(base);
1344
1345 // Clobber all fields of escaped references of the same type.
1346 for (uint16_t escaped_ref : escaped_refs_) {
1347 EscapedIFieldClobberKey clobber_key = { escaped_ref, type, kNoValue };
1348 escaped_ifield_clobber_set_.insert(clobber_key);
1349 }
1350
1351 // Aliasing fields of the same type may have been overwritten.
1352 auto it = aliasing_ifield_value_map_.begin(), end = aliasing_ifield_value_map_.end();
1353 while (it != end) {
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001354 if (gvn_->GetIFieldType(it->first) != type) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001355 ++it;
1356 } else {
1357 it = aliasing_ifield_value_map_.erase(it);
1358 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001359 }
1360 } else if (field_info.IsVolatile()) {
1361 // Nothing to do, resolved volatile fields always get a new memory version anyway and
1362 // can't alias with resolved non-volatile fields.
1363 } else {
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001364 uint16_t field_id = gvn_->GetIFieldId(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001365 uint16_t value = (opcode == Instruction::IPUT_WIDE)
1366 ? GetOperandValueWide(mir->ssa_rep->uses[0])
1367 : GetOperandValue(mir->ssa_rep->uses[0]);
1368 if (IsNonAliasing(base)) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001369 uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
1370 auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
1371 if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
1372 if (lb->second == value) {
1373 // This IPUT can be eliminated, it stores the same value that's already in the field.
1374 // TODO: Eliminate the IPUT.
1375 return;
1376 }
1377 lb->second = value; // Overwrite.
1378 } else {
1379 non_aliasing_ifield_value_map_.PutBefore(lb, loc, value);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001380 }
Vladimir Marko95a05972014-05-30 10:01:32 +01001381 } else {
1382 bool put_is_live = HandleAliasingValuesPut<AliasingIFieldVersions>(
1383 &aliasing_ifield_value_map_, field_id, base, value);
1384 if (!put_is_live) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001385 // This IPUT can be eliminated, it stores the same value that's already in the field.
1386 // TODO: Eliminate the IPUT.
1387 return;
1388 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001389
Vladimir Marko95a05972014-05-30 10:01:32 +01001390 // Clobber all fields of escaped references for this field.
1391 for (uint16_t escaped_ref : escaped_refs_) {
1392 EscapedIFieldClobberKey clobber_key = { escaped_ref, type, field_id };
1393 escaped_ifield_clobber_set_.insert(clobber_key);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001394 }
1395 }
1396 }
1397}
1398
1399uint16_t LocalValueNumbering::HandleSGet(MIR* mir, uint16_t opcode) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001400 const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
Vladimir Markofa236452014-09-29 17:58:10 +01001401 if (!field_info.IsResolved() || field_info.IsVolatile() ||
Vladimir Marko66c6d7b2014-10-16 15:41:48 +01001402 (!field_info.IsClassInitialized() &&
1403 (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0)) {
Vladimir Markofa236452014-09-29 17:58:10 +01001404 // Volatile SGETs (and unresolved fields are potentially volatile) have acquire semantics
1405 // and class initialization can call arbitrary functions, we need to wipe aliasing values.
1406 HandleInvokeOrClInitOrAcquireOp(mir);
Vladimir Markof418f322014-07-09 14:45:36 +01001407 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001408 uint16_t res;
1409 if (!field_info.IsResolved() || field_info.IsVolatile()) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001410 // Unresolved fields may be volatile, so handle them as such to be safe.
Vladimir Markofa236452014-09-29 17:58:10 +01001411 // Volatile fields always get a new memory version; field id is irrelevant.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001412 // Use result s_reg - will be unique.
Vladimir Marko95a05972014-05-30 10:01:32 +01001413 res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001414 } else {
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001415 uint16_t type = SGetMemAccessType(static_cast<Instruction::Code>(opcode));
1416 uint16_t field_id = gvn_->GetSFieldId(mir);
Vladimir Marko95a05972014-05-30 10:01:32 +01001417 auto lb = sfield_value_map_.lower_bound(field_id);
1418 if (lb != sfield_value_map_.end() && lb->first == field_id) {
1419 res = lb->second;
1420 } else {
1421 // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
1422 // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
1423 // to determine the version of the field.
1424 res = gvn_->LookupValue(kResolvedSFieldOp, field_id,
1425 unresolved_sfield_version_[type], global_memory_version_);
1426 sfield_value_map_.PutBefore(lb, field_id, res);
1427 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001428 }
1429 if (opcode == Instruction::SGET_WIDE) {
1430 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1431 } else {
1432 SetOperandValue(mir->ssa_rep->defs[0], res);
1433 }
1434 return res;
1435}
1436
1437void LocalValueNumbering::HandleSPut(MIR* mir, uint16_t opcode) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001438 const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
Vladimir Marko66c6d7b2014-10-16 15:41:48 +01001439 if (!field_info.IsClassInitialized() &&
1440 (mir->optimization_flags & MIR_CLASS_IS_INITIALIZED) == 0) {
Vladimir Markof418f322014-07-09 14:45:36 +01001441 // Class initialization can call arbitrary functions, we need to wipe aliasing values.
Vladimir Markofa236452014-09-29 17:58:10 +01001442 HandleInvokeOrClInitOrAcquireOp(mir);
Vladimir Markof418f322014-07-09 14:45:36 +01001443 }
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001444 uint16_t type = SPutMemAccessType(static_cast<Instruction::Code>(opcode));
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001445 if (!field_info.IsResolved()) {
1446 // Unresolved fields always alias with everything of the same type.
1447 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1448 unresolved_sfield_version_[type] =
Vladimir Marko95a05972014-05-30 10:01:32 +01001449 gvn_->LookupValue(kUnresolvedSFieldOp, kNoValue, kNoValue, mir->offset);
1450 RemoveSFieldsForType(type);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001451 } else if (field_info.IsVolatile()) {
1452 // Nothing to do, resolved volatile fields always get a new memory version anyway and
1453 // can't alias with resolved non-volatile fields.
1454 } else {
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001455 uint16_t field_id = gvn_->GetSFieldId(mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001456 uint16_t value = (opcode == Instruction::SPUT_WIDE)
1457 ? GetOperandValueWide(mir->ssa_rep->uses[0])
1458 : GetOperandValue(mir->ssa_rep->uses[0]);
1459 // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
1460 // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
1461 // to determine the version of the field.
Vladimir Marko95a05972014-05-30 10:01:32 +01001462 auto lb = sfield_value_map_.lower_bound(field_id);
1463 if (lb != sfield_value_map_.end() && lb->first == field_id) {
1464 if (lb->second == value) {
1465 // This SPUT can be eliminated, it stores the same value that's already in the field.
1466 // TODO: Eliminate the SPUT.
1467 return;
1468 }
1469 lb->second = value; // Overwrite.
1470 } else {
1471 sfield_value_map_.PutBefore(lb, field_id, value);
1472 }
1473 }
1474}
1475
1476void LocalValueNumbering::RemoveSFieldsForType(uint16_t type) {
1477 // Erase all static fields of this type from the sfield_value_map_.
1478 for (auto it = sfield_value_map_.begin(), end = sfield_value_map_.end(); it != end; ) {
Vladimir Markoaf6925b2014-10-31 16:37:32 +00001479 if (gvn_->GetSFieldType(it->first) == type) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001480 it = sfield_value_map_.erase(it);
1481 } else {
1482 ++it;
1483 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001484 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001485}
buzbee2502e002012-12-31 16:05:53 -08001486
Vladimir Markofa236452014-09-29 17:58:10 +01001487void LocalValueNumbering::HandleInvokeOrClInitOrAcquireOp(MIR* mir) {
Vladimir Markof418f322014-07-09 14:45:36 +01001488 // Use mir->offset as modifier; without elaborate inlining, it will be unique.
Vladimir Marko95a05972014-05-30 10:01:32 +01001489 global_memory_version_ =
1490 gvn_->LookupValue(kInvokeMemoryVersionBumpOp, 0u, 0u, mir->offset);
1491 // All static fields and instance fields and array elements of aliasing references,
1492 // including escaped references, may have been modified.
1493 sfield_value_map_.clear();
1494 aliasing_ifield_value_map_.clear();
1495 aliasing_array_value_map_.clear();
1496 escaped_refs_.clear();
1497 escaped_ifield_clobber_set_.clear();
1498 escaped_array_clobber_set_.clear();
Vladimir Markof418f322014-07-09 14:45:36 +01001499}
1500
Brian Carlstrom2ce745c2013-07-17 17:44:30 -07001501uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001502 uint16_t res = kNoValue;
buzbee2502e002012-12-31 16:05:53 -08001503 uint16_t opcode = mir->dalvikInsn.opcode;
1504 switch (opcode) {
1505 case Instruction::NOP:
1506 case Instruction::RETURN_VOID:
1507 case Instruction::RETURN:
1508 case Instruction::RETURN_OBJECT:
1509 case Instruction::RETURN_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001510 case Instruction::GOTO:
1511 case Instruction::GOTO_16:
1512 case Instruction::GOTO_32:
buzbee2502e002012-12-31 16:05:53 -08001513 case Instruction::THROW:
1514 case Instruction::FILL_ARRAY_DATA:
buzbee2502e002012-12-31 16:05:53 -08001515 case Instruction::PACKED_SWITCH:
1516 case Instruction::SPARSE_SWITCH:
1517 case Instruction::IF_EQ:
1518 case Instruction::IF_NE:
1519 case Instruction::IF_LT:
1520 case Instruction::IF_GE:
1521 case Instruction::IF_GT:
1522 case Instruction::IF_LE:
1523 case Instruction::IF_EQZ:
1524 case Instruction::IF_NEZ:
1525 case Instruction::IF_LTZ:
1526 case Instruction::IF_GEZ:
1527 case Instruction::IF_GTZ:
1528 case Instruction::IF_LEZ:
buzbee2502e002012-12-31 16:05:53 -08001529 case kMirOpFusedCmplFloat:
1530 case kMirOpFusedCmpgFloat:
1531 case kMirOpFusedCmplDouble:
1532 case kMirOpFusedCmpgDouble:
1533 case kMirOpFusedCmpLong:
1534 // Nothing defined - take no action.
1535 break;
1536
Vladimir Marko95a05972014-05-30 10:01:32 +01001537 case Instruction::MONITOR_ENTER:
1538 HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
Vladimir Markofa236452014-09-29 17:58:10 +01001539 HandleInvokeOrClInitOrAcquireOp(mir); // Acquire operation.
Vladimir Marko95a05972014-05-30 10:01:32 +01001540 break;
1541
1542 case Instruction::MONITOR_EXIT:
1543 HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
1544 // If we're running GVN and CanModify(), uneliminated null check indicates bytecode error.
Vladimir Marko415ac882014-09-30 18:09:14 +01001545 if ((mir->optimization_flags & MIR_IGNORE_NULL_CHECK) == 0 &&
1546 gvn_->work_lvn_ != nullptr && gvn_->CanModify()) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001547 LOG(WARNING) << "Bytecode error: MONITOR_EXIT is still null checked at 0x" << std::hex
1548 << mir->offset << " in " << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file);
1549 }
1550 break;
1551
Vladimir Markof59f18b2014-02-17 15:53:57 +00001552 case Instruction::FILLED_NEW_ARRAY:
1553 case Instruction::FILLED_NEW_ARRAY_RANGE:
1554 // Nothing defined but the result will be unique and non-null.
1555 if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
Vladimir Marko95a05972014-05-30 10:01:32 +01001556 uint16_t array = MarkNonAliasingNonNull(mir->next);
1557 // Do not SetOperandValue(), we'll do that when we process the MOVE_RESULT_OBJECT.
1558 if (kLocalValueNumberingEnableFilledNewArrayTracking && mir->ssa_rep->num_uses != 0u) {
1559 AliasingValues* values = GetAliasingValues(&non_aliasing_array_value_map_, array);
1560 // Clear the value if we got a merged version in a loop.
Vladimir Markob19955d2014-07-29 12:04:10 +01001561 *values = AliasingValues(this);
Vladimir Marko95a05972014-05-30 10:01:32 +01001562 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1563 DCHECK_EQ(High16Bits(i), 0u);
1564 uint16_t index = gvn_->LookupValue(Instruction::CONST, i, 0u, 0);
1565 uint16_t value = GetOperandValue(mir->ssa_rep->uses[i]);
1566 values->load_value_map.Put(index, value);
1567 RangeCheckKey key = { array, index };
1568 range_checked_.insert(key);
1569 }
1570 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001571 // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
1572 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001573 // All args escaped (if references).
1574 for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1575 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
1576 HandleEscapingRef(reg);
1577 }
Vladimir Markof59f18b2014-02-17 15:53:57 +00001578 break;
1579
Vladimir Markoa78e66a2014-10-16 13:38:44 +01001580 case kMirOpNullCheck:
1581 HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
1582 break;
1583
Vladimir Markof59f18b2014-02-17 15:53:57 +00001584 case Instruction::INVOKE_DIRECT:
1585 case Instruction::INVOKE_DIRECT_RANGE:
1586 case Instruction::INVOKE_VIRTUAL:
1587 case Instruction::INVOKE_VIRTUAL_RANGE:
1588 case Instruction::INVOKE_SUPER:
1589 case Instruction::INVOKE_SUPER_RANGE:
1590 case Instruction::INVOKE_INTERFACE:
1591 case Instruction::INVOKE_INTERFACE_RANGE: {
1592 // Nothing defined but handle the null check.
1593 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
1594 HandleNullCheck(mir, reg);
1595 }
Ian Rogersfc787ec2014-10-09 21:56:44 -07001596 FALLTHROUGH_INTENDED;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001597 case Instruction::INVOKE_STATIC:
1598 case Instruction::INVOKE_STATIC_RANGE:
Vladimir Markoff0ac472014-10-02 17:24:53 +01001599 // Make ref args aliasing.
Vladimir Markoa4426cf2014-10-22 17:15:53 +01001600 HandleInvokeArgs(mir, this);
Vladimir Markoff0ac472014-10-02 17:24:53 +01001601 HandleInvokeOrClInitOrAcquireOp(mir);
Vladimir Markof59f18b2014-02-17 15:53:57 +00001602 break;
1603
Vladimir Marko22fe45d2015-03-18 11:33:58 +00001604 case Instruction::INSTANCE_OF: {
1605 uint16_t operand = GetOperandValue(mir->ssa_rep->uses[0]);
1606 uint16_t type = mir->dalvikInsn.vC;
1607 res = gvn_->LookupValue(Instruction::INSTANCE_OF, operand, type, kNoValue);
1608 SetOperandValue(mir->ssa_rep->defs[0], res);
1609 }
1610 break;
1611 case Instruction::CHECK_CAST:
1612 if (gvn_->CanModify()) {
1613 // Check if there was an instance-of operation on the same value and if we are
1614 // in a block where its result is true. If so, we can eliminate the check-cast.
1615 uint16_t operand = GetOperandValue(mir->ssa_rep->uses[0]);
1616 uint16_t type = mir->dalvikInsn.vB;
1617 uint16_t cond = gvn_->FindValue(Instruction::INSTANCE_OF, operand, type, kNoValue);
1618 if (cond != kNoValue && gvn_->IsTrueInBlock(cond, Id())) {
1619 if (gvn_->GetCompilationUnit()->verbose) {
1620 LOG(INFO) << "Removing check-cast at 0x" << std::hex << mir->offset;
1621 }
1622 // Don't use kMirOpNop. Keep the check-cast as it defines the type of the register.
1623 mir->optimization_flags |= MIR_IGNORE_CHECK_CAST;
1624 }
1625 }
1626 break;
1627
buzbee2502e002012-12-31 16:05:53 -08001628 case Instruction::MOVE_RESULT:
1629 case Instruction::MOVE_RESULT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001630 // 1 result, treat as unique each time, use result s_reg - will be unique.
1631 res = GetOperandValue(mir->ssa_rep->defs[0]);
1632 SetOperandValue(mir->ssa_rep->defs[0], res);
1633 break;
1634 case Instruction::MOVE_EXCEPTION:
buzbee2502e002012-12-31 16:05:53 -08001635 case Instruction::NEW_INSTANCE:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001636 case Instruction::NEW_ARRAY:
Vladimir Markob3e527b2014-04-04 12:37:07 +01001637 // 1 result, treat as unique each time, use result s_reg - will be unique.
1638 res = MarkNonAliasingNonNull(mir);
Vladimir Marko95a05972014-05-30 10:01:32 +01001639 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001640 break;
Vladimir Marko7a01dc22015-01-02 17:00:44 +00001641 case Instruction::CONST_CLASS:
1642 DCHECK_EQ(Low16Bits(mir->dalvikInsn.vB), mir->dalvikInsn.vB);
1643 res = gvn_->LookupValue(Instruction::CONST_CLASS, mir->dalvikInsn.vB, 0, 0);
1644 SetOperandValue(mir->ssa_rep->defs[0], res);
1645 null_checked_.insert(res);
1646 non_aliasing_refs_.insert(res);
1647 break;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001648 case Instruction::CONST_STRING:
1649 case Instruction::CONST_STRING_JUMBO:
1650 // These strings are internalized, so assign value based on the string pool index.
Vladimir Marko95a05972014-05-30 10:01:32 +01001651 res = gvn_->LookupValue(Instruction::CONST_STRING, Low16Bits(mir->dalvikInsn.vB),
1652 High16Bits(mir->dalvikInsn.vB), 0);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001653 SetOperandValue(mir->ssa_rep->defs[0], res);
1654 null_checked_.insert(res); // May already be there.
1655 // NOTE: Hacking the contents of an internalized string via reflection is possible
1656 // but the behavior is undefined. Therefore, we consider the string constant and
1657 // the reference non-aliasing.
1658 // TUNING: We could keep this property even if the reference "escapes".
1659 non_aliasing_refs_.insert(res); // May already be there.
1660 break;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001661 case Instruction::MOVE_RESULT_WIDE:
Vladimir Markob3e527b2014-04-04 12:37:07 +01001662 // 1 wide result, treat as unique each time, use result s_reg - will be unique.
1663 res = GetOperandValueWide(mir->ssa_rep->defs[0]);
1664 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001665 break;
1666
1667 case kMirOpPhi:
Vladimir Marko95a05972014-05-30 10:01:32 +01001668 res = HandlePhi(mir);
buzbee2502e002012-12-31 16:05:53 -08001669 break;
1670
1671 case Instruction::MOVE:
1672 case Instruction::MOVE_OBJECT:
1673 case Instruction::MOVE_16:
1674 case Instruction::MOVE_OBJECT_16:
1675 case Instruction::MOVE_FROM16:
1676 case Instruction::MOVE_OBJECT_FROM16:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001677 case kMirOpCopy:
1678 // Just copy value number of source to value number of result.
1679 res = GetOperandValue(mir->ssa_rep->uses[0]);
1680 SetOperandValue(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001681 break;
1682
1683 case Instruction::MOVE_WIDE:
1684 case Instruction::MOVE_WIDE_16:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001685 case Instruction::MOVE_WIDE_FROM16:
1686 // Just copy value number of source to value number of result.
1687 res = GetOperandValueWide(mir->ssa_rep->uses[0]);
1688 SetOperandValueWide(mir->ssa_rep->defs[0], res);
buzbee2502e002012-12-31 16:05:53 -08001689 break;
1690
Vladimir Marko7a01dc22015-01-02 17:00:44 +00001691 case Instruction::CONST_HIGH16:
Vladimir Marko22c7f5b2015-02-18 17:52:39 +00001692 res = HandleConst(mir, mir->dalvikInsn.vB << 16);
1693 break;
buzbee2502e002012-12-31 16:05:53 -08001694 case Instruction::CONST:
1695 case Instruction::CONST_4:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001696 case Instruction::CONST_16:
Vladimir Marko22c7f5b2015-02-18 17:52:39 +00001697 res = HandleConst(mir, mir->dalvikInsn.vB);
buzbee2502e002012-12-31 16:05:53 -08001698 break;
1699
1700 case Instruction::CONST_WIDE_16:
Vladimir Marko22c7f5b2015-02-18 17:52:39 +00001701 case Instruction::CONST_WIDE_32:
1702 res = HandleConstWide(
1703 mir,
1704 mir->dalvikInsn.vB +
1705 ((mir->dalvikInsn.vB & 0x80000000) != 0 ? UINT64_C(0xffffffff00000000) : 0u));
buzbee2502e002012-12-31 16:05:53 -08001706 break;
1707
Vladimir Marko22c7f5b2015-02-18 17:52:39 +00001708 case Instruction::CONST_WIDE:
1709 res = HandleConstWide(mir, mir->dalvikInsn.vB_wide);
buzbee2502e002012-12-31 16:05:53 -08001710 break;
1711
Vladimir Marko22c7f5b2015-02-18 17:52:39 +00001712 case Instruction::CONST_WIDE_HIGH16:
1713 res = HandleConstWide(mir, static_cast<uint64_t>(mir->dalvikInsn.vB) << 48);
buzbee2502e002012-12-31 16:05:53 -08001714 break;
1715
Vladimir Marko95a05972014-05-30 10:01:32 +01001716 case Instruction::ARRAY_LENGTH: {
1717 // Handle the null check.
1718 uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
1719 HandleNullCheck(mir, reg);
1720 }
Ian Rogersfc787ec2014-10-09 21:56:44 -07001721 FALLTHROUGH_INTENDED;
buzbee2502e002012-12-31 16:05:53 -08001722 case Instruction::NEG_INT:
1723 case Instruction::NOT_INT:
1724 case Instruction::NEG_FLOAT:
1725 case Instruction::INT_TO_BYTE:
1726 case Instruction::INT_TO_SHORT:
1727 case Instruction::INT_TO_CHAR:
1728 case Instruction::INT_TO_FLOAT:
1729 case Instruction::FLOAT_TO_INT: {
1730 // res = op + 1 operand
1731 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001732 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001733 SetOperandValue(mir->ssa_rep->defs[0], res);
1734 }
1735 break;
1736
1737 case Instruction::LONG_TO_FLOAT:
1738 case Instruction::LONG_TO_INT:
1739 case Instruction::DOUBLE_TO_FLOAT:
1740 case Instruction::DOUBLE_TO_INT: {
1741 // res = op + 1 wide operand
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001742 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001743 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001744 SetOperandValue(mir->ssa_rep->defs[0], res);
1745 }
1746 break;
1747
buzbee2502e002012-12-31 16:05:53 -08001748 case Instruction::DOUBLE_TO_LONG:
1749 case Instruction::LONG_TO_DOUBLE:
1750 case Instruction::NEG_LONG:
1751 case Instruction::NOT_LONG:
1752 case Instruction::NEG_DOUBLE: {
1753 // wide res = op + 1 wide operand
1754 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001755 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001756 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1757 }
1758 break;
1759
1760 case Instruction::FLOAT_TO_DOUBLE:
1761 case Instruction::FLOAT_TO_LONG:
1762 case Instruction::INT_TO_DOUBLE:
1763 case Instruction::INT_TO_LONG: {
1764 // wide res = op + 1 operand
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001765 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001766 res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001767 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1768 }
1769 break;
1770
1771 case Instruction::CMPL_DOUBLE:
1772 case Instruction::CMPG_DOUBLE:
1773 case Instruction::CMP_LONG: {
1774 // res = op + 2 wide operands
1775 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1776 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001777 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001778 SetOperandValue(mir->ssa_rep->defs[0], res);
1779 }
1780 break;
1781
Razvan A Lupusorue0951142014-11-14 14:36:55 -08001782 case Instruction::DIV_INT:
1783 case Instruction::DIV_INT_2ADDR:
1784 case Instruction::REM_INT:
1785 case Instruction::REM_INT_2ADDR:
1786 HandleDivZeroCheck(mir, GetOperandValue(mir->ssa_rep->uses[1]));
1787 FALLTHROUGH_INTENDED;
1788
buzbee2502e002012-12-31 16:05:53 -08001789 case Instruction::CMPG_FLOAT:
1790 case Instruction::CMPL_FLOAT:
1791 case Instruction::ADD_INT:
1792 case Instruction::ADD_INT_2ADDR:
1793 case Instruction::MUL_INT:
1794 case Instruction::MUL_INT_2ADDR:
1795 case Instruction::AND_INT:
1796 case Instruction::AND_INT_2ADDR:
1797 case Instruction::OR_INT:
1798 case Instruction::OR_INT_2ADDR:
1799 case Instruction::XOR_INT:
1800 case Instruction::XOR_INT_2ADDR:
1801 case Instruction::SUB_INT:
1802 case Instruction::SUB_INT_2ADDR:
buzbee2502e002012-12-31 16:05:53 -08001803 case Instruction::SHL_INT:
1804 case Instruction::SHL_INT_2ADDR:
1805 case Instruction::SHR_INT:
1806 case Instruction::SHR_INT_2ADDR:
1807 case Instruction::USHR_INT:
1808 case Instruction::USHR_INT_2ADDR: {
1809 // res = op + 2 operands
1810 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1811 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001812 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001813 SetOperandValue(mir->ssa_rep->defs[0], res);
1814 }
1815 break;
1816
Razvan A Lupusorue0951142014-11-14 14:36:55 -08001817 case Instruction::DIV_LONG:
1818 case Instruction::REM_LONG:
1819 case Instruction::DIV_LONG_2ADDR:
1820 case Instruction::REM_LONG_2ADDR:
1821 HandleDivZeroCheck(mir, GetOperandValueWide(mir->ssa_rep->uses[2]));
1822 FALLTHROUGH_INTENDED;
1823
buzbee2502e002012-12-31 16:05:53 -08001824 case Instruction::ADD_LONG:
1825 case Instruction::SUB_LONG:
1826 case Instruction::MUL_LONG:
buzbee2502e002012-12-31 16:05:53 -08001827 case Instruction::AND_LONG:
1828 case Instruction::OR_LONG:
1829 case Instruction::XOR_LONG:
1830 case Instruction::ADD_LONG_2ADDR:
1831 case Instruction::SUB_LONG_2ADDR:
1832 case Instruction::MUL_LONG_2ADDR:
buzbee2502e002012-12-31 16:05:53 -08001833 case Instruction::AND_LONG_2ADDR:
1834 case Instruction::OR_LONG_2ADDR:
1835 case Instruction::XOR_LONG_2ADDR:
1836 case Instruction::ADD_DOUBLE:
1837 case Instruction::SUB_DOUBLE:
1838 case Instruction::MUL_DOUBLE:
1839 case Instruction::DIV_DOUBLE:
1840 case Instruction::REM_DOUBLE:
1841 case Instruction::ADD_DOUBLE_2ADDR:
1842 case Instruction::SUB_DOUBLE_2ADDR:
1843 case Instruction::MUL_DOUBLE_2ADDR:
1844 case Instruction::DIV_DOUBLE_2ADDR:
1845 case Instruction::REM_DOUBLE_2ADDR: {
1846 // wide res = op + 2 wide operands
1847 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1848 uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001849 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001850 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1851 }
1852 break;
1853
1854 case Instruction::SHL_LONG:
1855 case Instruction::SHR_LONG:
1856 case Instruction::USHR_LONG:
1857 case Instruction::SHL_LONG_2ADDR:
1858 case Instruction::SHR_LONG_2ADDR:
1859 case Instruction::USHR_LONG_2ADDR: {
1860 // wide res = op + 1 wide operand + 1 operand
1861 uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001862 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[2]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001863 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001864 SetOperandValueWide(mir->ssa_rep->defs[0], res);
1865 }
1866 break;
1867
1868 case Instruction::ADD_FLOAT:
1869 case Instruction::SUB_FLOAT:
1870 case Instruction::MUL_FLOAT:
1871 case Instruction::DIV_FLOAT:
1872 case Instruction::REM_FLOAT:
1873 case Instruction::ADD_FLOAT_2ADDR:
1874 case Instruction::SUB_FLOAT_2ADDR:
1875 case Instruction::MUL_FLOAT_2ADDR:
1876 case Instruction::DIV_FLOAT_2ADDR:
1877 case Instruction::REM_FLOAT_2ADDR: {
1878 // res = op + 2 operands
1879 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1880 uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001881 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001882 SetOperandValue(mir->ssa_rep->defs[0], res);
1883 }
1884 break;
1885
1886 case Instruction::RSUB_INT:
1887 case Instruction::ADD_INT_LIT16:
1888 case Instruction::MUL_INT_LIT16:
1889 case Instruction::DIV_INT_LIT16:
1890 case Instruction::REM_INT_LIT16:
1891 case Instruction::AND_INT_LIT16:
1892 case Instruction::OR_INT_LIT16:
1893 case Instruction::XOR_INT_LIT16:
1894 case Instruction::ADD_INT_LIT8:
1895 case Instruction::RSUB_INT_LIT8:
1896 case Instruction::MUL_INT_LIT8:
1897 case Instruction::DIV_INT_LIT8:
1898 case Instruction::REM_INT_LIT8:
1899 case Instruction::AND_INT_LIT8:
1900 case Instruction::OR_INT_LIT8:
1901 case Instruction::XOR_INT_LIT8:
1902 case Instruction::SHL_INT_LIT8:
1903 case Instruction::SHR_INT_LIT8:
1904 case Instruction::USHR_INT_LIT8: {
nikolay serdjukee40aa42014-03-25 12:21:29 +07001905 // Same as res = op + 2 operands, except use vC as operand 2
buzbee2502e002012-12-31 16:05:53 -08001906 uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
Vladimir Marko95a05972014-05-30 10:01:32 +01001907 uint16_t operand2 = gvn_->LookupValue(Instruction::CONST, mir->dalvikInsn.vC, 0, 0);
1908 res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
buzbee2502e002012-12-31 16:05:53 -08001909 SetOperandValue(mir->ssa_rep->defs[0], res);
1910 }
1911 break;
1912
buzbee2502e002012-12-31 16:05:53 -08001913 case Instruction::AGET_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001914 case Instruction::AGET:
1915 case Instruction::AGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001916 case Instruction::AGET_BOOLEAN:
1917 case Instruction::AGET_BYTE:
1918 case Instruction::AGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001919 case Instruction::AGET_SHORT:
1920 res = HandleAGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001921 break;
1922
buzbee2502e002012-12-31 16:05:53 -08001923 case Instruction::APUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001924 HandlePutObject(mir);
Ian Rogersfc787ec2014-10-09 21:56:44 -07001925 FALLTHROUGH_INTENDED;
Vladimir Markof59f18b2014-02-17 15:53:57 +00001926 case Instruction::APUT:
1927 case Instruction::APUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001928 case Instruction::APUT_BYTE:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001929 case Instruction::APUT_BOOLEAN:
1930 case Instruction::APUT_SHORT:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001931 case Instruction::APUT_CHAR:
1932 HandleAPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001933 break;
1934
1935 case Instruction::IGET_OBJECT:
buzbee2502e002012-12-31 16:05:53 -08001936 case Instruction::IGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001937 case Instruction::IGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001938 case Instruction::IGET_BOOLEAN:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001939 case Instruction::IGET_BYTE:
1940 case Instruction::IGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001941 case Instruction::IGET_SHORT:
1942 res = HandleIGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001943 break;
1944
buzbee2502e002012-12-31 16:05:53 -08001945 case Instruction::IPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001946 HandlePutObject(mir);
Ian Rogersfc787ec2014-10-09 21:56:44 -07001947 FALLTHROUGH_INTENDED;
buzbee2502e002012-12-31 16:05:53 -08001948 case Instruction::IPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001949 case Instruction::IPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001950 case Instruction::IPUT_BOOLEAN:
1951 case Instruction::IPUT_BYTE:
1952 case Instruction::IPUT_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001953 case Instruction::IPUT_SHORT:
1954 HandleIPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001955 break;
1956
1957 case Instruction::SGET_OBJECT:
1958 case Instruction::SGET:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001959 case Instruction::SGET_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001960 case Instruction::SGET_BOOLEAN:
1961 case Instruction::SGET_BYTE:
1962 case Instruction::SGET_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001963 case Instruction::SGET_SHORT:
1964 res = HandleSGet(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001965 break;
1966
1967 case Instruction::SPUT_OBJECT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001968 HandlePutObject(mir);
Ian Rogersfc787ec2014-10-09 21:56:44 -07001969 FALLTHROUGH_INTENDED;
buzbee2502e002012-12-31 16:05:53 -08001970 case Instruction::SPUT:
Vladimir Markof59f18b2014-02-17 15:53:57 +00001971 case Instruction::SPUT_WIDE:
buzbee2502e002012-12-31 16:05:53 -08001972 case Instruction::SPUT_BOOLEAN:
1973 case Instruction::SPUT_BYTE:
1974 case Instruction::SPUT_CHAR:
Vladimir Marko2ac01fc2014-05-22 12:09:08 +01001975 case Instruction::SPUT_SHORT:
1976 HandleSPut(mir, opcode);
buzbee2502e002012-12-31 16:05:53 -08001977 break;
buzbee2502e002012-12-31 16:05:53 -08001978 }
1979 return res;
1980}
1981
Vladimir Marko7a01dc22015-01-02 17:00:44 +00001982uint16_t LocalValueNumbering::GetEndingVregValueNumberImpl(int v_reg, bool wide) const {
1983 const BasicBlock* bb = gvn_->GetBasicBlock(Id());
1984 DCHECK(bb != nullptr);
1985 int s_reg = bb->data_flow_info->vreg_to_ssa_map_exit[v_reg];
1986 if (s_reg == INVALID_SREG) {
1987 return kNoValue;
1988 }
Vladimir Markoa5e69e82015-04-24 19:03:51 +01001989 if (gvn_->GetMirGraph()->GetRegLocation(s_reg).wide != wide) {
1990 return kNoValue;
1991 }
Vladimir Marko7a01dc22015-01-02 17:00:44 +00001992 if (wide) {
1993 int high_s_reg = bb->data_flow_info->vreg_to_ssa_map_exit[v_reg + 1];
1994 if (high_s_reg != s_reg + 1) {
1995 return kNoValue; // High word has been overwritten.
1996 }
1997 return GetSregValueWide(s_reg);
1998 } else {
1999 return GetSregValue(s_reg);
2000 }
2001}
2002
2003uint16_t LocalValueNumbering::GetStartingVregValueNumberImpl(int v_reg, bool wide) const {
2004 DCHECK_EQ(gvn_->mode_, GlobalValueNumbering::kModeGvnPostProcessing);
2005 DCHECK(gvn_->CanModify());
2006 const BasicBlock* bb = gvn_->GetBasicBlock(Id());
2007 DCHECK(bb != nullptr);
2008 DCHECK_NE(bb->predecessors.size(), 0u);
2009 if (bb->predecessors.size() == 1u) {
2010 return gvn_->GetLvn(bb->predecessors[0])->GetEndingVregValueNumberImpl(v_reg, wide);
2011 }
2012 merge_names_.clear();
2013 uint16_t value_name = kNoValue;
2014 bool same_values = true;
2015 for (BasicBlockId pred_id : bb->predecessors) {
2016 value_name = gvn_->GetLvn(pred_id)->GetEndingVregValueNumberImpl(v_reg, wide);
2017 if (value_name == kNoValue) {
2018 return kNoValue;
2019 }
2020 same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
2021 merge_names_.push_back(value_name);
2022 }
2023 if (same_values) {
2024 // value_name already contains the result.
2025 } else {
2026 auto lb = merge_map_.lower_bound(merge_names_);
2027 if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
2028 value_name = lb->second;
2029 } else {
2030 value_name = kNoValue; // We never assigned a value name to this set of merged names.
2031 }
2032 }
2033 return value_name;
2034}
2035
buzbee2502e002012-12-31 16:05:53 -08002036} // namespace art