• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 #include "local_value_numbering.h"
18 
19 #include "global_value_numbering.h"
20 #include "mir_field_info.h"
21 #include "mir_graph.h"
22 
23 namespace art {
24 
25 namespace {  // anonymous namespace
26 
27 // Operations used for value map keys instead of actual opcode.
28 static constexpr uint16_t kInvokeMemoryVersionBumpOp = Instruction::INVOKE_VIRTUAL;
29 static constexpr uint16_t kUnresolvedSFieldOp = Instruction::SGET;
30 static constexpr uint16_t kResolvedSFieldOp = Instruction::SGET_WIDE;
31 static constexpr uint16_t kUnresolvedIFieldOp = Instruction::IGET;
32 static constexpr uint16_t kNonAliasingIFieldLocOp = Instruction::IGET_WIDE;
33 static constexpr uint16_t kNonAliasingIFieldInitialOp = Instruction::IGET_OBJECT;
34 static constexpr uint16_t kAliasingIFieldOp = Instruction::IGET_BOOLEAN;
35 static constexpr uint16_t kAliasingIFieldStartVersionOp = Instruction::IGET_BYTE;
36 static constexpr uint16_t kAliasingIFieldBumpVersionOp = Instruction::IGET_CHAR;
37 static constexpr uint16_t kNonAliasingArrayOp = Instruction::AGET;
38 static constexpr uint16_t kNonAliasingArrayStartVersionOp = Instruction::AGET_WIDE;
39 static constexpr uint16_t kNonAliasingArrayBumpVersionOp = Instruction::AGET_OBJECT;
40 static constexpr uint16_t kAliasingArrayOp = Instruction::AGET_BOOLEAN;
41 static constexpr uint16_t kAliasingArrayStartVersionOp = Instruction::AGET_BYTE;
42 static constexpr uint16_t kAliasingArrayBumpVersionOp = Instruction::AGET_CHAR;
43 static constexpr uint16_t kMergeBlockMemoryVersionBumpOp = Instruction::INVOKE_VIRTUAL_RANGE;
44 static constexpr uint16_t kMergeBlockAliasingIFieldVersionBumpOp = Instruction::IPUT;
45 static constexpr uint16_t kMergeBlockAliasingIFieldMergeLocationOp = Instruction::IPUT_WIDE;
46 static constexpr uint16_t kMergeBlockNonAliasingArrayVersionBumpOp = Instruction::APUT;
47 static constexpr uint16_t kMergeBlockNonAliasingArrayMergeLocationOp = Instruction::APUT_WIDE;
48 static constexpr uint16_t kMergeBlockAliasingArrayVersionBumpOp = Instruction::APUT_OBJECT;
49 static constexpr uint16_t kMergeBlockAliasingArrayMergeLocationOp = Instruction::APUT_BOOLEAN;
50 static constexpr uint16_t kMergeBlockNonAliasingIFieldVersionBumpOp = Instruction::APUT_BYTE;
51 static constexpr uint16_t kMergeBlockSFieldVersionBumpOp = Instruction::APUT_CHAR;
52 
53 }  // anonymous namespace
54 
55 class LocalValueNumbering::AliasingIFieldVersions {
56  public:
StartMemoryVersion(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t field_id)57   static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
58                                      uint16_t field_id) {
59     uint16_t type = gvn->GetFieldType(field_id);
60     return gvn->LookupValue(kAliasingIFieldStartVersionOp, field_id,
61                             lvn->global_memory_version_, lvn->unresolved_ifield_version_[type]);
62   }
63 
BumpMemoryVersion(GlobalValueNumbering * gvn,uint16_t old_version,uint16_t store_ref_set_id,uint16_t stored_value)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 
LookupGlobalValue(GlobalValueNumbering * gvn,uint16_t field_id,uint16_t base,uint16_t memory_version)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 
LookupMergeValue(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t field_id,uint16_t base)75   static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
76                                    uint16_t field_id, uint16_t base) {
77     // If the base/field_id is non-aliasing in lvn, use the non-aliasing value.
78     uint16_t type = gvn->GetFieldType(field_id);
79     if (lvn->IsNonAliasingIField(base, field_id, type)) {
80       uint16_t loc = gvn->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
81       auto lb = lvn->non_aliasing_ifield_value_map_.find(loc);
82       return (lb != lvn->non_aliasing_ifield_value_map_.end())
83           ? lb->second
84           : gvn->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
85     }
86     return AliasingValuesMergeGet<AliasingIFieldVersions>(
87         gvn, lvn, &lvn->aliasing_ifield_value_map_, field_id, base);
88   }
89 
HasNewBaseVersion(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t field_id)90   static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
91                                 uint16_t field_id) {
92     uint16_t type = gvn->GetFieldType(field_id);
93     return lvn->unresolved_ifield_version_[type] == lvn->merge_new_memory_version_ ||
94         lvn->global_memory_version_ == lvn->merge_new_memory_version_;
95   }
96 
LookupMergeBlockValue(GlobalValueNumbering * gvn,uint16_t lvn_id,uint16_t field_id)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 
LookupMergeLocationValue(GlobalValueNumbering * gvn,uint16_t lvn_id,uint16_t field_id,uint16_t base)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 
108 class LocalValueNumbering::NonAliasingArrayVersions {
109  public:
StartMemoryVersion(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t array)110   static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
111                                      uint16_t array) {
112     return gvn->LookupValue(kNonAliasingArrayStartVersionOp, array, kNoValue, kNoValue);
113   }
114 
BumpMemoryVersion(GlobalValueNumbering * gvn,uint16_t old_version,uint16_t store_ref_set_id,uint16_t stored_value)115   static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
116                                     uint16_t store_ref_set_id, uint16_t stored_value) {
117     return gvn->LookupValue(kNonAliasingArrayBumpVersionOp, old_version,
118                             store_ref_set_id, stored_value);
119   }
120 
LookupGlobalValue(GlobalValueNumbering * gvn,uint16_t array,uint16_t index,uint16_t memory_version)121   static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
122                                     uint16_t array, uint16_t index, uint16_t memory_version) {
123     return gvn->LookupValue(kNonAliasingArrayOp, array, index, memory_version);
124   }
125 
LookupMergeValue(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t array,uint16_t index)126   static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
127                                    uint16_t array, uint16_t index) {
128     return AliasingValuesMergeGet<NonAliasingArrayVersions>(
129         gvn, lvn, &lvn->non_aliasing_array_value_map_, array, index);
130   }
131 
HasNewBaseVersion(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t array)132   static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
133                                 uint16_t array) {
134     return false;  // Not affected by global_memory_version_.
135   }
136 
LookupMergeBlockValue(GlobalValueNumbering * gvn,uint16_t lvn_id,uint16_t array)137   static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
138                                         uint16_t array) {
139     return gvn->LookupValue(kMergeBlockNonAliasingArrayVersionBumpOp, array, kNoValue, lvn_id);
140   }
141 
LookupMergeLocationValue(GlobalValueNumbering * gvn,uint16_t lvn_id,uint16_t array,uint16_t index)142   static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
143                                            uint16_t array, uint16_t index) {
144     return gvn->LookupValue(kMergeBlockNonAliasingArrayMergeLocationOp, array, index, lvn_id);
145   }
146 };
147 
148 class LocalValueNumbering::AliasingArrayVersions {
149  public:
StartMemoryVersion(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t type)150   static uint16_t StartMemoryVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
151                                      uint16_t type) {
152     return gvn->LookupValue(kAliasingArrayStartVersionOp, type, lvn->global_memory_version_,
153                             kNoValue);
154   }
155 
BumpMemoryVersion(GlobalValueNumbering * gvn,uint16_t old_version,uint16_t store_ref_set_id,uint16_t stored_value)156   static uint16_t BumpMemoryVersion(GlobalValueNumbering* gvn, uint16_t old_version,
157                                     uint16_t store_ref_set_id, uint16_t stored_value) {
158     return gvn->LookupValue(kAliasingArrayBumpVersionOp, old_version,
159                             store_ref_set_id, stored_value);
160   }
161 
LookupGlobalValue(GlobalValueNumbering * gvn,uint16_t type,uint16_t location,uint16_t memory_version)162   static uint16_t LookupGlobalValue(GlobalValueNumbering* gvn,
163                                     uint16_t type, uint16_t location, uint16_t memory_version) {
164     return gvn->LookupValue(kAliasingArrayOp, type, location, memory_version);
165   }
166 
LookupMergeValue(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t type,uint16_t location)167   static uint16_t LookupMergeValue(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
168                                    uint16_t type, uint16_t location) {
169     // If the location is non-aliasing in lvn, use the non-aliasing value.
170     uint16_t array = gvn->GetArrayLocationBase(location);
171     if (lvn->IsNonAliasingArray(array, type)) {
172       uint16_t index = gvn->GetArrayLocationIndex(location);
173       return NonAliasingArrayVersions::LookupMergeValue(gvn, lvn, array, index);
174     }
175     return AliasingValuesMergeGet<AliasingArrayVersions>(
176         gvn, lvn, &lvn->aliasing_array_value_map_, type, location);
177   }
178 
HasNewBaseVersion(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,uint16_t type)179   static bool HasNewBaseVersion(GlobalValueNumbering* gvn, const LocalValueNumbering* lvn,
180                                 uint16_t type) {
181     return lvn->global_memory_version_ == lvn->merge_new_memory_version_;
182   }
183 
LookupMergeBlockValue(GlobalValueNumbering * gvn,uint16_t lvn_id,uint16_t type)184   static uint16_t LookupMergeBlockValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
185                                         uint16_t type) {
186     return gvn->LookupValue(kMergeBlockAliasingArrayVersionBumpOp, type, kNoValue, lvn_id);
187   }
188 
LookupMergeLocationValue(GlobalValueNumbering * gvn,uint16_t lvn_id,uint16_t type,uint16_t location)189   static uint16_t LookupMergeLocationValue(GlobalValueNumbering* gvn, uint16_t lvn_id,
190                                            uint16_t type, uint16_t location) {
191     return gvn->LookupValue(kMergeBlockAliasingArrayMergeLocationOp, type, location, lvn_id);
192   }
193 };
194 
195 template <typename Map>
GetAliasingValues(Map * map,const typename Map::key_type & key)196 LocalValueNumbering::AliasingValues* LocalValueNumbering::GetAliasingValues(
197     Map* map, const typename Map::key_type& key) {
198   auto lb = map->lower_bound(key);
199   if (lb == map->end() || map->key_comp()(key, lb->first)) {
200     lb = map->PutBefore(lb, key, AliasingValues(this));
201   }
202   return &lb->second;
203 }
204 
205 template <typename Versions, typename KeyType>
UpdateAliasingValuesLoadVersion(const KeyType & key,AliasingValues * values)206 void LocalValueNumbering::UpdateAliasingValuesLoadVersion(const KeyType& key,
207                                                           AliasingValues* values) {
208   if (values->last_load_memory_version == kNoValue) {
209     // Get the start version that accounts for aliasing with unresolved fields of the same
210     // type and make it unique for the field by including the field_id.
211     uint16_t memory_version = values->memory_version_before_stores;
212     if (memory_version == kNoValue) {
213       memory_version = Versions::StartMemoryVersion(gvn_, this, key);
214     }
215     if (!values->store_loc_set.empty()) {
216       uint16_t ref_set_id = gvn_->GetRefSetId(values->store_loc_set);
217       memory_version = Versions::BumpMemoryVersion(gvn_, memory_version, ref_set_id,
218                                                    values->last_stored_value);
219     }
220     values->last_load_memory_version = memory_version;
221   }
222 }
223 
224 template <typename Versions, typename Map>
AliasingValuesMergeGet(GlobalValueNumbering * gvn,const LocalValueNumbering * lvn,Map * map,const typename Map::key_type & key,uint16_t location)225 uint16_t LocalValueNumbering::AliasingValuesMergeGet(GlobalValueNumbering* gvn,
226                                                      const LocalValueNumbering* lvn,
227                                                      Map* map, const typename Map::key_type& key,
228                                                      uint16_t location) {
229   // Retrieve the value name that we would get from
230   //   const_cast<LocalValueNumbering*>(lvn)->HandleAliasingValueGet(map. key, location)
231   // but don't modify the map.
232   uint16_t value_name;
233   auto it = map->find(key);
234   if (it == map->end()) {
235     uint16_t start_version = Versions::StartMemoryVersion(gvn, lvn, key);
236     value_name = Versions::LookupGlobalValue(gvn, key, location, start_version);
237   } else if (it->second.store_loc_set.count(location) != 0u) {
238     value_name = it->second.last_stored_value;
239   } else {
240     auto load_it = it->second.load_value_map.find(location);
241     if (load_it != it->second.load_value_map.end()) {
242       value_name = load_it->second;
243     } else {
244       value_name = Versions::LookupGlobalValue(gvn, key, location, it->second.last_load_memory_version);
245     }
246   }
247   return value_name;
248 }
249 
250 template <typename Versions, typename Map>
HandleAliasingValuesGet(Map * map,const typename Map::key_type & key,uint16_t location)251 uint16_t LocalValueNumbering::HandleAliasingValuesGet(Map* map, const typename Map::key_type& key,
252                                                       uint16_t location) {
253   // Retrieve the value name for IGET/SGET/AGET, update the map with new value if any.
254   uint16_t res;
255   AliasingValues* values = GetAliasingValues(map, key);
256   if (values->store_loc_set.count(location) != 0u) {
257     res = values->last_stored_value;
258   } else {
259     UpdateAliasingValuesLoadVersion<Versions>(key, values);
260     auto lb = values->load_value_map.lower_bound(location);
261     if (lb != values->load_value_map.end() && lb->first == location) {
262       res = lb->second;
263     } else {
264       res = Versions::LookupGlobalValue(gvn_, key, location, values->last_load_memory_version);
265       values->load_value_map.PutBefore(lb, location, res);
266     }
267   }
268   return res;
269 }
270 
271 template <typename Versions, typename Map>
HandleAliasingValuesPut(Map * map,const typename Map::key_type & key,uint16_t location,uint16_t value)272 bool LocalValueNumbering::HandleAliasingValuesPut(Map* map, const typename Map::key_type& key,
273                                                   uint16_t location, uint16_t value) {
274   AliasingValues* values = GetAliasingValues(map, key);
275   auto load_values_it = values->load_value_map.find(location);
276   if (load_values_it != values->load_value_map.end() && load_values_it->second == value) {
277     // This insn can be eliminated, it stores the same value that's already in the field.
278     return false;
279   }
280   if (value == values->last_stored_value) {
281     auto store_loc_lb = values->store_loc_set.lower_bound(location);
282     if (store_loc_lb != values->store_loc_set.end() && *store_loc_lb == location) {
283       // This insn can be eliminated, it stores the same value that's already in the field.
284       return false;
285     }
286     values->store_loc_set.emplace_hint(store_loc_lb, location);
287   } else {
288     UpdateAliasingValuesLoadVersion<Versions>(key, values);
289     values->memory_version_before_stores = values->last_load_memory_version;
290     values->last_stored_value = value;
291     values->store_loc_set.clear();
292     values->store_loc_set.insert(location);
293   }
294   // Clear the last load memory version and remove all potentially overwritten values.
295   values->last_load_memory_version = kNoValue;
296   auto it = values->load_value_map.begin(), end = values->load_value_map.end();
297   while (it != end) {
298     if (it->second == value) {
299       ++it;
300     } else {
301       it = values->load_value_map.erase(it);
302     }
303   }
304   return true;
305 }
306 
307 template <typename K>
CopyAliasingValuesMap(ScopedArenaSafeMap<K,AliasingValues> * dest,const ScopedArenaSafeMap<K,AliasingValues> & src)308 void LocalValueNumbering::CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
309                                                 const ScopedArenaSafeMap<K, AliasingValues>& src) {
310   // We need each new AliasingValues (or rather its map members) to be constructed
311   // with our allocator, rather than the allocator of the source.
312   for (const auto& entry : src) {
313     auto it = dest->PutBefore(dest->end(), entry.first, AliasingValues(this));
314     it->second = entry.second;  // Map assignments preserve current allocator.
315   }
316 }
317 
LocalValueNumbering(GlobalValueNumbering * gvn,uint16_t id,ScopedArenaAllocator * allocator)318 LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id,
319                                          ScopedArenaAllocator* allocator)
320     : gvn_(gvn),
321       id_(id),
322       sreg_value_map_(std::less<uint16_t>(), allocator->Adapter()),
323       sreg_wide_value_map_(std::less<uint16_t>(), allocator->Adapter()),
324       sfield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
325       non_aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
326       aliasing_ifield_value_map_(std::less<uint16_t>(), allocator->Adapter()),
327       non_aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
328       aliasing_array_value_map_(std::less<uint16_t>(), allocator->Adapter()),
329       global_memory_version_(0u),
330       non_aliasing_refs_(std::less<uint16_t>(), allocator->Adapter()),
331       escaped_refs_(std::less<uint16_t>(), allocator->Adapter()),
332       escaped_ifield_clobber_set_(EscapedIFieldClobberKeyComparator(), allocator->Adapter()),
333       escaped_array_clobber_set_(EscapedArrayClobberKeyComparator(), allocator->Adapter()),
334       range_checked_(RangeCheckKeyComparator() , allocator->Adapter()),
335       null_checked_(std::less<uint16_t>(), allocator->Adapter()),
336       merge_names_(allocator->Adapter()),
337       merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), allocator->Adapter()),
338       merge_new_memory_version_(kNoValue) {
339   std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
340   std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
341 }
342 
Equals(const LocalValueNumbering & other) const343 bool LocalValueNumbering::Equals(const LocalValueNumbering& other) const {
344   DCHECK(gvn_ == other.gvn_);
345   // Compare the maps/sets and memory versions.
346   return sreg_value_map_ == other.sreg_value_map_ &&
347       sreg_wide_value_map_ == other.sreg_wide_value_map_ &&
348       sfield_value_map_ == other.sfield_value_map_ &&
349       non_aliasing_ifield_value_map_ == other.non_aliasing_ifield_value_map_ &&
350       aliasing_ifield_value_map_ == other.aliasing_ifield_value_map_ &&
351       non_aliasing_array_value_map_ == other.non_aliasing_array_value_map_ &&
352       aliasing_array_value_map_ == other.aliasing_array_value_map_ &&
353       SameMemoryVersion(other) &&
354       non_aliasing_refs_ == other.non_aliasing_refs_ &&
355       escaped_refs_ == other.escaped_refs_ &&
356       escaped_ifield_clobber_set_ == other.escaped_ifield_clobber_set_ &&
357       escaped_array_clobber_set_ == other.escaped_array_clobber_set_ &&
358       range_checked_ == other.range_checked_ &&
359       null_checked_ == other.null_checked_;
360 }
361 
MergeOne(const LocalValueNumbering & other,MergeType merge_type)362 void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType merge_type) {
363   CopyLiveSregValues(&sreg_value_map_, other.sreg_value_map_);
364   CopyLiveSregValues(&sreg_wide_value_map_, other.sreg_wide_value_map_);
365 
366   if (merge_type == kReturnMerge) {
367     // RETURN or PHI+RETURN. We need only sreg value maps.
368     return;
369   }
370 
371   non_aliasing_ifield_value_map_ = other.non_aliasing_ifield_value_map_;
372   CopyAliasingValuesMap(&non_aliasing_array_value_map_, other.non_aliasing_array_value_map_);
373   non_aliasing_refs_ = other.non_aliasing_refs_;
374   range_checked_ = other.range_checked_;
375   null_checked_ = other.null_checked_;
376 
377   if (merge_type == kCatchMerge) {
378     // Memory is clobbered. Use new memory version and don't merge aliasing locations.
379     global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
380     std::fill_n(unresolved_sfield_version_, kFieldTypeCount, global_memory_version_);
381     std::fill_n(unresolved_ifield_version_, kFieldTypeCount, global_memory_version_);
382     PruneNonAliasingRefsForCatch();
383     return;
384   }
385 
386   DCHECK(merge_type == kNormalMerge);
387   global_memory_version_ = other.global_memory_version_;
388   std::copy_n(other.unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
389   std::copy_n(other.unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
390   sfield_value_map_ = other.sfield_value_map_;
391   CopyAliasingValuesMap(&aliasing_ifield_value_map_, other.aliasing_ifield_value_map_);
392   CopyAliasingValuesMap(&aliasing_array_value_map_, other.aliasing_array_value_map_);
393   escaped_refs_ = other.escaped_refs_;
394   escaped_ifield_clobber_set_ = other.escaped_ifield_clobber_set_;
395   escaped_array_clobber_set_ = other.escaped_array_clobber_set_;
396 }
397 
SameMemoryVersion(const LocalValueNumbering & other) const398 bool LocalValueNumbering::SameMemoryVersion(const LocalValueNumbering& other) const {
399   return
400       global_memory_version_ == other.global_memory_version_ &&
401       std::equal(unresolved_ifield_version_, unresolved_ifield_version_ + kFieldTypeCount,
402                  other.unresolved_ifield_version_) &&
403       std::equal(unresolved_sfield_version_, unresolved_sfield_version_ + kFieldTypeCount,
404                  other.unresolved_sfield_version_);
405 }
406 
NewMemoryVersion(uint16_t * new_version)407 uint16_t LocalValueNumbering::NewMemoryVersion(uint16_t* new_version) {
408   if (*new_version == kNoValue) {
409     *new_version = gvn_->LookupValue(kMergeBlockMemoryVersionBumpOp, 0u, 0u, id_);
410   }
411   return *new_version;
412 }
413 
MergeMemoryVersions(bool clobbered_catch)414 void LocalValueNumbering::MergeMemoryVersions(bool clobbered_catch) {
415   DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
416   const LocalValueNumbering* cmp = gvn_->merge_lvns_[0];
417   // Check if the global version has changed.
418   bool new_global_version = clobbered_catch;
419   if (!new_global_version) {
420     for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
421       if (lvn->global_memory_version_ != cmp->global_memory_version_) {
422         // Use a new version for everything.
423         new_global_version = true;
424         break;
425       }
426     }
427   }
428   if (new_global_version) {
429     global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
430     std::fill_n(unresolved_sfield_version_, kFieldTypeCount, merge_new_memory_version_);
431     std::fill_n(unresolved_ifield_version_, kFieldTypeCount, merge_new_memory_version_);
432   } else {
433     // Initialize with a copy of memory versions from the comparison LVN.
434     global_memory_version_ = cmp->global_memory_version_;
435     std::copy_n(cmp->unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
436     std::copy_n(cmp->unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
437     for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
438       if (lvn == cmp) {
439         continue;
440       }
441       for (size_t i = 0; i != kFieldTypeCount; ++i) {
442         if (lvn->unresolved_ifield_version_[i] != cmp->unresolved_ifield_version_[i]) {
443           unresolved_ifield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
444         }
445         if (lvn->unresolved_sfield_version_[i] != cmp->unresolved_sfield_version_[i]) {
446           unresolved_sfield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
447         }
448       }
449     }
450   }
451 }
452 
PruneNonAliasingRefsForCatch()453 void LocalValueNumbering::PruneNonAliasingRefsForCatch() {
454   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
455     const BasicBlock* bb = gvn_->GetBasicBlock(lvn->Id());
456     if (UNLIKELY(bb->taken == id_) || UNLIKELY(bb->fall_through == id_)) {
457       // Non-exceptional path to a catch handler means that the catch block was actually
458       // empty and all exceptional paths lead to the shared path after that empty block.
459       continue;
460     }
461     DCHECK_EQ(bb->taken, kNullBlock);
462     DCHECK_NE(bb->fall_through, kNullBlock);
463     const BasicBlock* fall_through_bb = gvn_->GetBasicBlock(bb->fall_through);
464     const MIR* mir = fall_through_bb->first_mir_insn;
465     DCHECK(mir != nullptr);
466     // Only INVOKEs can leak and clobber non-aliasing references if they throw.
467     if ((Instruction::FlagsOf(mir->dalvikInsn.opcode) & Instruction::kInvoke) != 0) {
468       for (uint16_t i = 0u; i != mir->ssa_rep->num_uses; ++i) {
469         uint16_t value_name = lvn->GetOperandValue(mir->ssa_rep->uses[i]);
470         non_aliasing_refs_.erase(value_name);
471       }
472     }
473   }
474 }
475 
476 
477 template <typename Set, Set LocalValueNumbering::* set_ptr>
IntersectSets()478 void LocalValueNumbering::IntersectSets() {
479   DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
480 
481   // Find the LVN with the least entries in the set.
482   const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
483   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
484     if ((lvn->*set_ptr).size() < (least_entries_lvn->*set_ptr).size()) {
485       least_entries_lvn = lvn;
486     }
487   }
488 
489   // For each key check if it's in all the LVNs.
490   for (const auto& key : least_entries_lvn->*set_ptr) {
491     bool checked = true;
492     for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
493       if (lvn != least_entries_lvn && (lvn->*set_ptr).count(key) == 0u) {
494         checked = false;
495         break;
496       }
497     }
498     if (checked) {
499       (this->*set_ptr).emplace_hint((this->*set_ptr).end(), key);
500     }
501   }
502 }
503 
CopyLiveSregValues(SregValueMap * dest,const SregValueMap & src)504 void LocalValueNumbering::CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src) {
505   auto dest_end = dest->end();
506   ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
507   DCHECK(live_in_v != nullptr);
508   for (const auto& entry : src) {
509     bool live = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
510     if (live) {
511       dest->PutBefore(dest_end, entry.first, entry.second);
512     }
513   }
514 }
515 
516 template <LocalValueNumbering::SregValueMap LocalValueNumbering::* map_ptr>
IntersectSregValueMaps()517 void LocalValueNumbering::IntersectSregValueMaps() {
518   DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
519 
520   // Find the LVN with the least entries in the set.
521   const LocalValueNumbering* least_entries_lvn = gvn_->merge_lvns_[0];
522   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
523     if ((lvn->*map_ptr).size() < (least_entries_lvn->*map_ptr).size()) {
524       least_entries_lvn = lvn;
525     }
526   }
527 
528   // For each key check if it's in all the LVNs.
529   ArenaBitVector* live_in_v = gvn_->GetMirGraph()->GetBasicBlock(id_)->data_flow_info->live_in_v;
530   DCHECK(live_in_v != nullptr);
531   for (const auto& entry : least_entries_lvn->*map_ptr) {
532     bool live_and_same = live_in_v->IsBitSet(gvn_->GetMirGraph()->SRegToVReg(entry.first));
533     if (live_and_same) {
534       for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
535         if (lvn != least_entries_lvn) {
536           auto it = (lvn->*map_ptr).find(entry.first);
537           if (it == (lvn->*map_ptr).end() || !(it->second == entry.second)) {
538             live_and_same = false;
539             break;
540           }
541         }
542       }
543     }
544     if (live_and_same) {
545       (this->*map_ptr).PutBefore((this->*map_ptr).end(), entry.first, entry.second);
546     }
547   }
548 }
549 
550 // Intersect maps as sets. The value type must be equality-comparable.
551 template <typename Map>
InPlaceIntersectMaps(Map * work_map,const Map & other_map)552 void LocalValueNumbering::InPlaceIntersectMaps(Map* work_map, const Map& other_map) {
553   auto work_it = work_map->begin(), work_end = work_map->end();
554   auto cmp = work_map->value_comp();
555   for (const auto& entry : other_map) {
556     while (work_it != work_end &&
557         (cmp(*work_it, entry) ||
558          (!cmp(entry, *work_it) && !(work_it->second == entry.second)))) {
559       work_it = work_map->erase(work_it);
560     }
561     if (work_it == work_end) {
562       return;
563     }
564     ++work_it;
565   }
566 }
567 
568 template <typename Set, Set LocalValueNumbering::*set_ptr, void (LocalValueNumbering::*MergeFn)(
569     const typename Set::value_type& entry, typename Set::iterator hint)>
MergeSets()570 void LocalValueNumbering::MergeSets() {
571   auto cmp = (this->*set_ptr).value_comp();
572   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
573     auto my_it = (this->*set_ptr).begin(), my_end = (this->*set_ptr).end();
574     for (const auto& entry : lvn->*set_ptr) {
575       while (my_it != my_end && cmp(*my_it, entry)) {
576         ++my_it;
577       }
578       if (my_it != my_end && !cmp(entry, *my_it)) {
579         // Already handled.
580         ++my_it;
581       } else {
582         // Merge values for this field_id.
583         (this->*MergeFn)(entry, my_it);  // my_it remains valid across inserts to std::set/SafeMap.
584       }
585     }
586   }
587 }
588 
IntersectAliasingValueLocations(AliasingValues * work_values,const AliasingValues * values)589 void LocalValueNumbering::IntersectAliasingValueLocations(AliasingValues* work_values,
590                                                           const AliasingValues* values) {
591   auto cmp = work_values->load_value_map.key_comp();
592   auto work_it = work_values->load_value_map.begin(), work_end = work_values->load_value_map.end();
593   auto store_it = values->store_loc_set.begin(), store_end = values->store_loc_set.end();
594   auto load_it = values->load_value_map.begin(), load_end = values->load_value_map.end();
595   while (store_it != store_end || load_it != load_end) {
596     uint16_t loc;
597     if (store_it != store_end && (load_it == load_end || *store_it < load_it->first)) {
598       loc = *store_it;
599       ++store_it;
600     } else {
601       loc = load_it->first;
602       ++load_it;
603       DCHECK(store_it == store_end || cmp(loc, *store_it));
604     }
605     while (work_it != work_end && cmp(work_it->first, loc)) {
606       work_it = work_values->load_value_map.erase(work_it);
607     }
608     if (work_it != work_end && !cmp(loc, work_it->first)) {
609       // The location matches, keep it.
610       ++work_it;
611     }
612   }
613   while (work_it != work_end) {
614     work_it = work_values->load_value_map.erase(work_it);
615   }
616 }
617 
MergeEscapedRefs(const ValueNameSet::value_type & entry,ValueNameSet::iterator hint)618 void LocalValueNumbering::MergeEscapedRefs(const ValueNameSet::value_type& entry,
619                                            ValueNameSet::iterator hint) {
620   // See if the ref is either escaped or non-aliasing in each predecessor.
621   bool is_escaped = true;
622   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
623     if (lvn->non_aliasing_refs_.count(entry) == 0u &&
624         lvn->escaped_refs_.count(entry) == 0u) {
625       is_escaped = false;
626       break;
627     }
628   }
629   if (is_escaped) {
630     escaped_refs_.emplace_hint(hint, entry);
631   }
632 }
633 
MergeEscapedIFieldTypeClobberSets(const EscapedIFieldClobberSet::value_type & entry,EscapedIFieldClobberSet::iterator hint)634 void LocalValueNumbering::MergeEscapedIFieldTypeClobberSets(
635     const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
636   // Insert only type-clobber entries (field_id == kNoValue) of escaped refs.
637   if (entry.field_id == kNoValue && escaped_refs_.count(entry.base) != 0u) {
638     escaped_ifield_clobber_set_.emplace_hint(hint, entry);
639   }
640 }
641 
MergeEscapedIFieldClobberSets(const EscapedIFieldClobberSet::value_type & entry,EscapedIFieldClobberSet::iterator hint)642 void LocalValueNumbering::MergeEscapedIFieldClobberSets(
643     const EscapedIFieldClobberSet::value_type& entry, EscapedIFieldClobberSet::iterator hint) {
644   // Insert only those entries of escaped refs that are not overridden by a type clobber.
645   if (!(hint == escaped_ifield_clobber_set_.end() &&
646         hint->base == entry.base && hint->type == entry.type) &&
647       escaped_refs_.count(entry.base) != 0u) {
648     escaped_ifield_clobber_set_.emplace_hint(hint, entry);
649   }
650 }
651 
MergeEscapedArrayClobberSets(const EscapedArrayClobberSet::value_type & entry,EscapedArrayClobberSet::iterator hint)652 void LocalValueNumbering::MergeEscapedArrayClobberSets(
653     const EscapedArrayClobberSet::value_type& entry, EscapedArrayClobberSet::iterator hint) {
654   if (escaped_refs_.count(entry.base) != 0u) {
655     escaped_array_clobber_set_.emplace_hint(hint, entry);
656   }
657 }
658 
MergeNullChecked(const ValueNameSet::value_type & entry,ValueNameSet::iterator hint)659 void LocalValueNumbering::MergeNullChecked(const ValueNameSet::value_type& entry,
660                                            ValueNameSet::iterator hint) {
661   // Merge null_checked_ for this ref.
662   merge_names_.clear();
663   merge_names_.resize(gvn_->merge_lvns_.size(), entry);
664   if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
665     null_checked_.insert(hint, entry);
666   }
667 }
668 
MergeSFieldValues(const SFieldToValueMap::value_type & entry,SFieldToValueMap::iterator hint)669 void LocalValueNumbering::MergeSFieldValues(const SFieldToValueMap::value_type& entry,
670                                             SFieldToValueMap::iterator hint) {
671   uint16_t field_id = entry.first;
672   merge_names_.clear();
673   uint16_t value_name = kNoValue;
674   bool same_values = true;
675   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
676     // Get the value name as in HandleSGet() but don't modify *lvn.
677     auto it = lvn->sfield_value_map_.find(field_id);
678     if (it != lvn->sfield_value_map_.end()) {
679       value_name = it->second;
680     } else {
681       uint16_t type = gvn_->GetFieldType(field_id);
682       value_name = gvn_->LookupValue(kResolvedSFieldOp, field_id,
683                                      lvn->unresolved_sfield_version_[type],
684                                      lvn->global_memory_version_);
685     }
686 
687     same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
688     merge_names_.push_back(value_name);
689   }
690   if (same_values) {
691     // value_name already contains the result.
692   } else {
693     auto lb = merge_map_.lower_bound(merge_names_);
694     if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
695       value_name = lb->second;
696     } else {
697       value_name = gvn_->LookupValue(kMergeBlockSFieldVersionBumpOp, field_id, id_, kNoValue);
698       merge_map_.PutBefore(lb, merge_names_, value_name);
699       if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
700         null_checked_.insert(value_name);
701       }
702     }
703   }
704   sfield_value_map_.PutBefore(hint, field_id, value_name);
705 }
706 
MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type & entry,IFieldLocToValueMap::iterator hint)707 void LocalValueNumbering::MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type& entry,
708                                                        IFieldLocToValueMap::iterator hint) {
709   uint16_t field_loc = entry.first;
710   merge_names_.clear();
711   uint16_t value_name = kNoValue;
712   bool same_values = true;
713   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
714     // Get the value name as in HandleIGet() but don't modify *lvn.
715     auto it = lvn->non_aliasing_ifield_value_map_.find(field_loc);
716     if (it != lvn->non_aliasing_ifield_value_map_.end()) {
717       value_name = it->second;
718     } else {
719       value_name = gvn_->LookupValue(kNonAliasingIFieldInitialOp, field_loc, kNoValue, kNoValue);
720     }
721 
722     same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
723     merge_names_.push_back(value_name);
724   }
725   if (same_values) {
726     // value_name already contains the result.
727   } else {
728     auto lb = merge_map_.lower_bound(merge_names_);
729     if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
730       value_name = lb->second;
731     } else {
732       value_name = gvn_->LookupValue(kMergeBlockNonAliasingIFieldVersionBumpOp, field_loc,
733                                      id_, kNoValue);
734       merge_map_.PutBefore(lb, merge_names_, value_name);
735       if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
736         null_checked_.insert(value_name);
737       }
738     }
739   }
740   non_aliasing_ifield_value_map_.PutBefore(hint, field_loc, value_name);
741 }
742 
743 template <typename Map, Map LocalValueNumbering::*map_ptr, typename Versions>
MergeAliasingValues(const typename Map::value_type & entry,typename Map::iterator hint)744 void LocalValueNumbering::MergeAliasingValues(const typename Map::value_type& entry,
745                                               typename Map::iterator hint) {
746   const typename Map::key_type& key = entry.first;
747 
748   auto it = (this->*map_ptr).PutBefore(hint, key, AliasingValues(this));
749   AliasingValues* my_values = &it->second;
750 
751   const AliasingValues* cmp_values = nullptr;
752   bool same_version = !Versions::HasNewBaseVersion(gvn_, this, key);
753   uint16_t load_memory_version_for_same_version = kNoValue;
754   if (same_version) {
755     // Find the first non-null values.
756     for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
757       auto it = (lvn->*map_ptr).find(key);
758       if (it != (lvn->*map_ptr).end()) {
759         cmp_values = &it->second;
760         break;
761       }
762     }
763     DCHECK(cmp_values != nullptr);  // There must be at least one non-null values.
764 
765     // Check if we have identical memory versions, i.e. the global memory version, unresolved
766     // field version and the values' memory_version_before_stores, last_stored_value
767     // and store_loc_set are identical.
768     for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
769       auto it = (lvn->*map_ptr).find(key);
770       if (it == (lvn->*map_ptr).end()) {
771         if (cmp_values->memory_version_before_stores != kNoValue) {
772           same_version = false;
773           break;
774         }
775       } else if (cmp_values->last_stored_value != it->second.last_stored_value ||
776           cmp_values->memory_version_before_stores != it->second.memory_version_before_stores ||
777           cmp_values->store_loc_set != it->second.store_loc_set) {
778         same_version = false;
779         break;
780       } else if (it->second.last_load_memory_version != kNoValue) {
781         DCHECK(load_memory_version_for_same_version == kNoValue ||
782                load_memory_version_for_same_version == it->second.last_load_memory_version);
783         load_memory_version_for_same_version = it->second.last_load_memory_version;
784       }
785     }
786   }
787 
788   if (same_version) {
789     // Copy the identical values.
790     my_values->memory_version_before_stores = cmp_values->memory_version_before_stores;
791     my_values->last_stored_value = cmp_values->last_stored_value;
792     my_values->store_loc_set = cmp_values->store_loc_set;
793     my_values->last_load_memory_version = load_memory_version_for_same_version;
794     // Merge load values seen in all incoming arcs (i.e. an intersection).
795     if (!cmp_values->load_value_map.empty()) {
796       my_values->load_value_map = cmp_values->load_value_map;
797       for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
798         auto it = (lvn->*map_ptr).find(key);
799         if (it == (lvn->*map_ptr).end() || it->second.load_value_map.empty()) {
800           my_values->load_value_map.clear();
801           break;
802         }
803         InPlaceIntersectMaps(&my_values->load_value_map, it->second.load_value_map);
804         if (my_values->load_value_map.empty()) {
805           break;
806         }
807       }
808     }
809   } else {
810     // Bump version number for the merge.
811     my_values->memory_version_before_stores = my_values->last_load_memory_version =
812         Versions::LookupMergeBlockValue(gvn_, id_, key);
813 
814     // Calculate the locations that have been either read from or written to in each incoming LVN.
815     bool first_lvn = true;
816     for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
817       auto it = (lvn->*map_ptr).find(key);
818       if (it == (lvn->*map_ptr).end()) {
819         my_values->load_value_map.clear();
820         break;
821       }
822       if (first_lvn) {
823         first_lvn = false;
824         // Copy the first LVN's locations. Values will be overwritten later.
825         my_values->load_value_map = it->second.load_value_map;
826         for (uint16_t location : it->second.store_loc_set) {
827           my_values->load_value_map.Put(location, 0u);
828         }
829       } else {
830         IntersectAliasingValueLocations(my_values, &it->second);
831       }
832     }
833     // Calculate merged values for the intersection.
834     for (auto& load_value_entry : my_values->load_value_map) {
835       uint16_t location = load_value_entry.first;
836       bool same_values = true;
837       uint16_t value_name = kNoValue;
838       merge_names_.clear();
839       for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
840         value_name = Versions::LookupMergeValue(gvn_, lvn, key, location);
841         same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
842         merge_names_.push_back(value_name);
843       }
844       if (same_values) {
845         // value_name already contains the result.
846       } else {
847         auto lb = merge_map_.lower_bound(merge_names_);
848         if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
849           value_name = lb->second;
850         } else {
851           // NOTE: In addition to the key and id_ which don't change on an LVN recalculation
852           // during GVN, we also add location which can actually change on recalculation, so the
853           // value_name below may change. This could lead to an infinite loop if the location
854           // value name always changed when the refereced value name changes. However, given that
855           // we assign unique value names for other merges, such as Phis, such a dependency is
856           // not possible in a well-formed SSA graph.
857           value_name = Versions::LookupMergeLocationValue(gvn_, id_, key, location);
858           merge_map_.PutBefore(lb, merge_names_, value_name);
859           if (gvn_->NullCheckedInAllPredecessors(merge_names_)) {
860             null_checked_.insert(value_name);
861           }
862         }
863       }
864       load_value_entry.second = value_name;
865     }
866   }
867 }
868 
Merge(MergeType merge_type)869 void LocalValueNumbering::Merge(MergeType merge_type) {
870   DCHECK_GE(gvn_->merge_lvns_.size(), 2u);
871 
872   IntersectSregValueMaps<&LocalValueNumbering::sreg_value_map_>();
873   IntersectSregValueMaps<&LocalValueNumbering::sreg_wide_value_map_>();
874   if (merge_type == kReturnMerge) {
875     // RETURN or PHI+RETURN. We need only sreg value maps.
876     return;
877   }
878 
879   MergeMemoryVersions(merge_type == kCatchMerge);
880 
881   // Merge non-aliasing maps/sets.
882   IntersectSets<ValueNameSet, &LocalValueNumbering::non_aliasing_refs_>();
883   if (!non_aliasing_refs_.empty() && merge_type == kCatchMerge) {
884     PruneNonAliasingRefsForCatch();
885   }
886   if (!non_aliasing_refs_.empty()) {
887     MergeSets<IFieldLocToValueMap, &LocalValueNumbering::non_aliasing_ifield_value_map_,
888               &LocalValueNumbering::MergeNonAliasingIFieldValues>();
889     MergeSets<NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
890               &LocalValueNumbering::MergeAliasingValues<
891                   NonAliasingArrayValuesMap, &LocalValueNumbering::non_aliasing_array_value_map_,
892                   NonAliasingArrayVersions>>();
893   }
894 
895   // We won't do anything complicated for range checks, just calculate the intersection.
896   IntersectSets<RangeCheckSet, &LocalValueNumbering::range_checked_>();
897 
898   // Merge null_checked_. We may later insert more, such as merged object field values.
899   MergeSets<ValueNameSet, &LocalValueNumbering::null_checked_,
900             &LocalValueNumbering::MergeNullChecked>();
901 
902   if (merge_type == kCatchMerge) {
903     // Memory is clobbered. New memory version already created, don't merge aliasing locations.
904     return;
905   }
906 
907   DCHECK(merge_type == kNormalMerge);
908 
909   // Merge escaped refs and clobber sets.
910   MergeSets<ValueNameSet, &LocalValueNumbering::escaped_refs_,
911             &LocalValueNumbering::MergeEscapedRefs>();
912   if (!escaped_refs_.empty()) {
913     MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
914               &LocalValueNumbering::MergeEscapedIFieldTypeClobberSets>();
915     MergeSets<EscapedIFieldClobberSet, &LocalValueNumbering::escaped_ifield_clobber_set_,
916               &LocalValueNumbering::MergeEscapedIFieldClobberSets>();
917     MergeSets<EscapedArrayClobberSet, &LocalValueNumbering::escaped_array_clobber_set_,
918               &LocalValueNumbering::MergeEscapedArrayClobberSets>();
919   }
920 
921   MergeSets<SFieldToValueMap, &LocalValueNumbering::sfield_value_map_,
922             &LocalValueNumbering::MergeSFieldValues>();
923   MergeSets<AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
924             &LocalValueNumbering::MergeAliasingValues<
925                 AliasingIFieldValuesMap, &LocalValueNumbering::aliasing_ifield_value_map_,
926                 AliasingIFieldVersions>>();
927   MergeSets<AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
928             &LocalValueNumbering::MergeAliasingValues<
929                 AliasingArrayValuesMap, &LocalValueNumbering::aliasing_array_value_map_,
930                 AliasingArrayVersions>>();
931 }
932 
MarkNonAliasingNonNull(MIR * mir)933 uint16_t LocalValueNumbering::MarkNonAliasingNonNull(MIR* mir) {
934   uint16_t res = GetOperandValue(mir->ssa_rep->defs[0]);
935   DCHECK(null_checked_.find(res) == null_checked_.end());
936   null_checked_.insert(res);
937   non_aliasing_refs_.insert(res);
938   return res;
939 }
940 
IsNonAliasing(uint16_t reg) const941 bool LocalValueNumbering::IsNonAliasing(uint16_t reg) const {
942   return non_aliasing_refs_.find(reg) != non_aliasing_refs_.end();
943 }
944 
IsNonAliasingIField(uint16_t reg,uint16_t field_id,uint16_t type) const945 bool LocalValueNumbering::IsNonAliasingIField(uint16_t reg, uint16_t field_id,
946                                               uint16_t type) const {
947   if (IsNonAliasing(reg)) {
948     return true;
949   }
950   if (escaped_refs_.find(reg) == escaped_refs_.end()) {
951     return false;
952   }
953   // Check for IPUTs to unresolved fields.
954   EscapedIFieldClobberKey key1 = { reg, type, kNoValue };
955   if (escaped_ifield_clobber_set_.find(key1) != escaped_ifield_clobber_set_.end()) {
956     return false;
957   }
958   // Check for aliased IPUTs to the same field.
959   EscapedIFieldClobberKey key2 = { reg, type, field_id };
960   return escaped_ifield_clobber_set_.find(key2) == escaped_ifield_clobber_set_.end();
961 }
962 
IsNonAliasingArray(uint16_t reg,uint16_t type) const963 bool LocalValueNumbering::IsNonAliasingArray(uint16_t reg, uint16_t type) const {
964   if (IsNonAliasing(reg)) {
965     return true;
966   }
967   if (escaped_refs_.count(reg) == 0u) {
968     return false;
969   }
970   // Check for aliased APUTs.
971   EscapedArrayClobberKey key = { reg, type };
972   return escaped_array_clobber_set_.find(key) == escaped_array_clobber_set_.end();
973 }
974 
HandleNullCheck(MIR * mir,uint16_t reg)975 void LocalValueNumbering::HandleNullCheck(MIR* mir, uint16_t reg) {
976   auto lb = null_checked_.lower_bound(reg);
977   if (lb != null_checked_.end() && *lb == reg) {
978     if (LIKELY(gvn_->CanModify())) {
979       if (gvn_->GetCompilationUnit()->verbose) {
980         LOG(INFO) << "Removing null check for 0x" << std::hex << mir->offset;
981       }
982       mir->optimization_flags |= MIR_IGNORE_NULL_CHECK;
983     }
984   } else {
985     null_checked_.insert(lb, reg);
986   }
987 }
988 
HandleRangeCheck(MIR * mir,uint16_t array,uint16_t index)989 void LocalValueNumbering::HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index) {
990   RangeCheckKey key = { array, index };
991   auto lb = range_checked_.lower_bound(key);
992   if (lb != range_checked_.end() && !RangeCheckKeyComparator()(key, *lb)) {
993     if (LIKELY(gvn_->CanModify())) {
994       if (gvn_->GetCompilationUnit()->verbose) {
995         LOG(INFO) << "Removing range check for 0x" << std::hex << mir->offset;
996       }
997       mir->optimization_flags |= MIR_IGNORE_RANGE_CHECK;
998     }
999   } else {
1000     // Mark range check completed.
1001     range_checked_.insert(lb, key);
1002   }
1003 }
1004 
HandlePutObject(MIR * mir)1005 void LocalValueNumbering::HandlePutObject(MIR* mir) {
1006   // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now.
1007   uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
1008   HandleEscapingRef(base);
1009 }
1010 
HandleEscapingRef(uint16_t base)1011 void LocalValueNumbering::HandleEscapingRef(uint16_t base) {
1012   auto it = non_aliasing_refs_.find(base);
1013   if (it != non_aliasing_refs_.end()) {
1014     non_aliasing_refs_.erase(it);
1015     escaped_refs_.insert(base);
1016   }
1017 }
1018 
HandlePhi(MIR * mir)1019 uint16_t LocalValueNumbering::HandlePhi(MIR* mir) {
1020   if (gvn_->merge_lvns_.empty()) {
1021     // Running LVN without a full GVN?
1022     return kNoValue;
1023   }
1024   int16_t num_uses = mir->ssa_rep->num_uses;
1025   int32_t* uses = mir->ssa_rep->uses;
1026   // Try to find out if this is merging wide regs.
1027   if (mir->ssa_rep->defs[0] != 0 &&
1028       sreg_wide_value_map_.count(mir->ssa_rep->defs[0] - 1) != 0u) {
1029     // This is the high part of a wide reg. Ignore the Phi.
1030     return kNoValue;
1031   }
1032   bool wide = false;
1033   for (int16_t i = 0; i != num_uses; ++i) {
1034     if (sreg_wide_value_map_.count(uses[i]) != 0u) {
1035       wide = true;
1036       break;
1037     }
1038   }
1039   // Iterate over *merge_lvns_ and skip incoming sregs for BBs without associated LVN.
1040   uint16_t value_name = kNoValue;
1041   merge_names_.clear();
1042   BasicBlockId* incoming = mir->meta.phi_incoming;
1043   int16_t pos = 0;
1044   bool same_values = true;
1045   for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
1046     DCHECK_LT(pos, mir->ssa_rep->num_uses);
1047     while (incoming[pos] != lvn->Id()) {
1048       ++pos;
1049       DCHECK_LT(pos, mir->ssa_rep->num_uses);
1050     }
1051     int s_reg = uses[pos];
1052     ++pos;
1053     value_name = wide ? lvn->GetOperandValueWide(s_reg) : lvn->GetOperandValue(s_reg);
1054 
1055     same_values = same_values && (merge_names_.empty() || value_name == merge_names_.back());
1056     merge_names_.push_back(value_name);
1057   }
1058   if (same_values) {
1059     // value_name already contains the result.
1060   } else {
1061     auto lb = merge_map_.lower_bound(merge_names_);
1062     if (lb != merge_map_.end() && !merge_map_.key_comp()(merge_names_, lb->first)) {
1063       value_name = lb->second;
1064     } else {
1065       value_name = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
1066       merge_map_.PutBefore(lb, merge_names_, value_name);
1067       if (!wide && gvn_->NullCheckedInAllPredecessors(merge_names_)) {
1068         null_checked_.insert(value_name);
1069       }
1070     }
1071   }
1072   if (wide) {
1073     SetOperandValueWide(mir->ssa_rep->defs[0], value_name);
1074   } else {
1075     SetOperandValue(mir->ssa_rep->defs[0], value_name);
1076   }
1077   return value_name;
1078 }
1079 
HandleAGet(MIR * mir,uint16_t opcode)1080 uint16_t LocalValueNumbering::HandleAGet(MIR* mir, uint16_t opcode) {
1081   // uint16_t type = opcode - Instruction::AGET;
1082   uint16_t array = GetOperandValue(mir->ssa_rep->uses[0]);
1083   HandleNullCheck(mir, array);
1084   uint16_t index = GetOperandValue(mir->ssa_rep->uses[1]);
1085   HandleRangeCheck(mir, array, index);
1086   uint16_t type = opcode - Instruction::AGET;
1087   // Establish value number for loaded register.
1088   uint16_t res;
1089   if (IsNonAliasingArray(array, type)) {
1090     res = HandleAliasingValuesGet<NonAliasingArrayVersions>(&non_aliasing_array_value_map_,
1091                                                             array, index);
1092   } else {
1093     uint16_t location = gvn_->GetArrayLocation(array, index);
1094     res = HandleAliasingValuesGet<AliasingArrayVersions>(&aliasing_array_value_map_,
1095                                                          type, location);
1096   }
1097   if (opcode == Instruction::AGET_WIDE) {
1098     SetOperandValueWide(mir->ssa_rep->defs[0], res);
1099   } else {
1100     SetOperandValue(mir->ssa_rep->defs[0], res);
1101   }
1102   return res;
1103 }
1104 
HandleAPut(MIR * mir,uint16_t opcode)1105 void LocalValueNumbering::HandleAPut(MIR* mir, uint16_t opcode) {
1106   int array_idx = (opcode == Instruction::APUT_WIDE) ? 2 : 1;
1107   int index_idx = array_idx + 1;
1108   uint16_t array = GetOperandValue(mir->ssa_rep->uses[array_idx]);
1109   HandleNullCheck(mir, array);
1110   uint16_t index = GetOperandValue(mir->ssa_rep->uses[index_idx]);
1111   HandleRangeCheck(mir, array, index);
1112 
1113   uint16_t type = opcode - Instruction::APUT;
1114   uint16_t value = (opcode == Instruction::APUT_WIDE)
1115                    ? GetOperandValueWide(mir->ssa_rep->uses[0])
1116                    : GetOperandValue(mir->ssa_rep->uses[0]);
1117   if (IsNonAliasing(array)) {
1118     bool put_is_live = HandleAliasingValuesPut<NonAliasingArrayVersions>(
1119         &non_aliasing_array_value_map_, array, index, value);
1120     if (!put_is_live) {
1121       // This APUT can be eliminated, it stores the same value that's already in the field.
1122       // TODO: Eliminate the APUT.
1123       return;
1124     }
1125   } else {
1126     uint16_t location = gvn_->GetArrayLocation(array, index);
1127     bool put_is_live = HandleAliasingValuesPut<AliasingArrayVersions>(
1128         &aliasing_array_value_map_, type, location, value);
1129     if (!put_is_live) {
1130       // This APUT can be eliminated, it stores the same value that's already in the field.
1131       // TODO: Eliminate the APUT.
1132       return;
1133     }
1134 
1135     // Clobber all escaped array refs for this type.
1136     for (uint16_t escaped_array : escaped_refs_) {
1137       EscapedArrayClobberKey clobber_key = { escaped_array, type };
1138       escaped_array_clobber_set_.insert(clobber_key);
1139     }
1140   }
1141 }
1142 
HandleIGet(MIR * mir,uint16_t opcode)1143 uint16_t LocalValueNumbering::HandleIGet(MIR* mir, uint16_t opcode) {
1144   uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]);
1145   HandleNullCheck(mir, base);
1146   const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
1147   uint16_t res;
1148   if (!field_info.IsResolved() || field_info.IsVolatile()) {
1149     // Volatile fields always get a new memory version; field id is irrelevant.
1150     // Unresolved fields may be volatile, so handle them as such to be safe.
1151     // Use result s_reg - will be unique.
1152     res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
1153   } else {
1154     uint16_t type = opcode - Instruction::IGET;
1155     uint16_t field_id = gvn_->GetFieldId(field_info, type);
1156     if (IsNonAliasingIField(base, field_id, type)) {
1157       uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
1158       auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
1159       if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
1160         res = lb->second;
1161       } else {
1162         res = gvn_->LookupValue(kNonAliasingIFieldInitialOp, loc, kNoValue, kNoValue);
1163         non_aliasing_ifield_value_map_.PutBefore(lb, loc, res);
1164       }
1165     } else {
1166       res = HandleAliasingValuesGet<AliasingIFieldVersions>(&aliasing_ifield_value_map_,
1167                                                             field_id, base);
1168     }
1169   }
1170   if (opcode == Instruction::IGET_WIDE) {
1171     SetOperandValueWide(mir->ssa_rep->defs[0], res);
1172   } else {
1173     SetOperandValue(mir->ssa_rep->defs[0], res);
1174   }
1175   return res;
1176 }
1177 
HandleIPut(MIR * mir,uint16_t opcode)1178 void LocalValueNumbering::HandleIPut(MIR* mir, uint16_t opcode) {
1179   uint16_t type = opcode - Instruction::IPUT;
1180   int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1;
1181   uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]);
1182   HandleNullCheck(mir, base);
1183   const MirFieldInfo& field_info = gvn_->GetMirGraph()->GetIFieldLoweringInfo(mir);
1184   if (!field_info.IsResolved()) {
1185     // Unresolved fields always alias with everything of the same type.
1186     // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1187     unresolved_ifield_version_[type] =
1188         gvn_->LookupValue(kUnresolvedIFieldOp, kNoValue, kNoValue, mir->offset);
1189 
1190     // For simplicity, treat base as escaped now.
1191     HandleEscapingRef(base);
1192 
1193     // Clobber all fields of escaped references of the same type.
1194     for (uint16_t escaped_ref : escaped_refs_) {
1195       EscapedIFieldClobberKey clobber_key = { escaped_ref, type, kNoValue };
1196       escaped_ifield_clobber_set_.insert(clobber_key);
1197     }
1198 
1199     // Aliasing fields of the same type may have been overwritten.
1200     auto it = aliasing_ifield_value_map_.begin(), end = aliasing_ifield_value_map_.end();
1201     while (it != end) {
1202       if (gvn_->GetFieldType(it->first) != type) {
1203         ++it;
1204       } else {
1205         it = aliasing_ifield_value_map_.erase(it);
1206       }
1207     }
1208   } else if (field_info.IsVolatile()) {
1209     // Nothing to do, resolved volatile fields always get a new memory version anyway and
1210     // can't alias with resolved non-volatile fields.
1211   } else {
1212     uint16_t field_id = gvn_->GetFieldId(field_info, type);
1213     uint16_t value = (opcode == Instruction::IPUT_WIDE)
1214                      ? GetOperandValueWide(mir->ssa_rep->uses[0])
1215                      : GetOperandValue(mir->ssa_rep->uses[0]);
1216     if (IsNonAliasing(base)) {
1217       uint16_t loc = gvn_->LookupValue(kNonAliasingIFieldLocOp, base, field_id, type);
1218       auto lb = non_aliasing_ifield_value_map_.lower_bound(loc);
1219       if (lb != non_aliasing_ifield_value_map_.end() && lb->first == loc) {
1220         if (lb->second == value) {
1221           // This IPUT can be eliminated, it stores the same value that's already in the field.
1222           // TODO: Eliminate the IPUT.
1223           return;
1224         }
1225         lb->second = value;  // Overwrite.
1226       } else {
1227         non_aliasing_ifield_value_map_.PutBefore(lb, loc, value);
1228       }
1229     } else {
1230       bool put_is_live = HandleAliasingValuesPut<AliasingIFieldVersions>(
1231           &aliasing_ifield_value_map_, field_id, base, value);
1232       if (!put_is_live) {
1233         // This IPUT can be eliminated, it stores the same value that's already in the field.
1234         // TODO: Eliminate the IPUT.
1235         return;
1236       }
1237 
1238       // Clobber all fields of escaped references for this field.
1239       for (uint16_t escaped_ref : escaped_refs_) {
1240         EscapedIFieldClobberKey clobber_key = { escaped_ref, type, field_id };
1241         escaped_ifield_clobber_set_.insert(clobber_key);
1242       }
1243     }
1244   }
1245 }
1246 
HandleSGet(MIR * mir,uint16_t opcode)1247 uint16_t LocalValueNumbering::HandleSGet(MIR* mir, uint16_t opcode) {
1248   const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
1249   if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
1250     // Class initialization can call arbitrary functions, we need to wipe aliasing values.
1251     HandleInvokeOrClInit(mir);
1252   }
1253   uint16_t res;
1254   if (!field_info.IsResolved() || field_info.IsVolatile()) {
1255     // Volatile fields always get a new memory version; field id is irrelevant.
1256     // Unresolved fields may be volatile, so handle them as such to be safe.
1257     // Use result s_reg - will be unique.
1258     res = gvn_->LookupValue(kNoValue, mir->ssa_rep->defs[0], kNoValue, kNoValue);
1259   } else {
1260     uint16_t type = opcode - Instruction::SGET;
1261     uint16_t field_id = gvn_->GetFieldId(field_info, type);
1262     auto lb = sfield_value_map_.lower_bound(field_id);
1263     if (lb != sfield_value_map_.end() && lb->first == field_id) {
1264       res = lb->second;
1265     } else {
1266       // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
1267       // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
1268       // to determine the version of the field.
1269       res = gvn_->LookupValue(kResolvedSFieldOp, field_id,
1270                               unresolved_sfield_version_[type], global_memory_version_);
1271       sfield_value_map_.PutBefore(lb, field_id, res);
1272     }
1273   }
1274   if (opcode == Instruction::SGET_WIDE) {
1275     SetOperandValueWide(mir->ssa_rep->defs[0], res);
1276   } else {
1277     SetOperandValue(mir->ssa_rep->defs[0], res);
1278   }
1279   return res;
1280 }
1281 
HandleSPut(MIR * mir,uint16_t opcode)1282 void LocalValueNumbering::HandleSPut(MIR* mir, uint16_t opcode) {
1283   const MirSFieldLoweringInfo& field_info = gvn_->GetMirGraph()->GetSFieldLoweringInfo(mir);
1284   if (!field_info.IsInitialized() && (mir->optimization_flags & MIR_IGNORE_CLINIT_CHECK) == 0) {
1285     // Class initialization can call arbitrary functions, we need to wipe aliasing values.
1286     HandleInvokeOrClInit(mir);
1287   }
1288   uint16_t type = opcode - Instruction::SPUT;
1289   if (!field_info.IsResolved()) {
1290     // Unresolved fields always alias with everything of the same type.
1291     // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1292     unresolved_sfield_version_[type] =
1293         gvn_->LookupValue(kUnresolvedSFieldOp, kNoValue, kNoValue, mir->offset);
1294     RemoveSFieldsForType(type);
1295   } else if (field_info.IsVolatile()) {
1296     // Nothing to do, resolved volatile fields always get a new memory version anyway and
1297     // can't alias with resolved non-volatile fields.
1298   } else {
1299     uint16_t field_id = gvn_->GetFieldId(field_info, type);
1300     uint16_t value = (opcode == Instruction::SPUT_WIDE)
1301                      ? GetOperandValueWide(mir->ssa_rep->uses[0])
1302                      : GetOperandValue(mir->ssa_rep->uses[0]);
1303     // Resolved non-volatile static fields can alias with non-resolved fields of the same type,
1304     // so we need to use unresolved_sfield_version_[type] in addition to global_memory_version_
1305     // to determine the version of the field.
1306     auto lb = sfield_value_map_.lower_bound(field_id);
1307     if (lb != sfield_value_map_.end() && lb->first == field_id) {
1308       if (lb->second == value) {
1309         // This SPUT can be eliminated, it stores the same value that's already in the field.
1310         // TODO: Eliminate the SPUT.
1311         return;
1312       }
1313       lb->second = value;  // Overwrite.
1314     } else {
1315       sfield_value_map_.PutBefore(lb, field_id, value);
1316     }
1317   }
1318 }
1319 
RemoveSFieldsForType(uint16_t type)1320 void LocalValueNumbering::RemoveSFieldsForType(uint16_t type) {
1321   // Erase all static fields of this type from the sfield_value_map_.
1322   for (auto it = sfield_value_map_.begin(), end = sfield_value_map_.end(); it != end; ) {
1323     if (gvn_->GetFieldType(it->first) == type) {
1324       it = sfield_value_map_.erase(it);
1325     } else {
1326       ++it;
1327     }
1328   }
1329 }
1330 
HandleInvokeOrClInit(MIR * mir)1331 void LocalValueNumbering::HandleInvokeOrClInit(MIR* mir) {
1332   // Use mir->offset as modifier; without elaborate inlining, it will be unique.
1333   global_memory_version_ =
1334       gvn_->LookupValue(kInvokeMemoryVersionBumpOp, 0u, 0u, mir->offset);
1335   // All static fields and instance fields and array elements of aliasing references,
1336   // including escaped references, may have been modified.
1337   sfield_value_map_.clear();
1338   aliasing_ifield_value_map_.clear();
1339   aliasing_array_value_map_.clear();
1340   escaped_refs_.clear();
1341   escaped_ifield_clobber_set_.clear();
1342   escaped_array_clobber_set_.clear();
1343 }
1344 
GetValueNumber(MIR * mir)1345 uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) {
1346   uint16_t res = kNoValue;
1347   uint16_t opcode = mir->dalvikInsn.opcode;
1348   switch (opcode) {
1349     case Instruction::NOP:
1350     case Instruction::RETURN_VOID:
1351     case Instruction::RETURN:
1352     case Instruction::RETURN_OBJECT:
1353     case Instruction::RETURN_WIDE:
1354     case Instruction::GOTO:
1355     case Instruction::GOTO_16:
1356     case Instruction::GOTO_32:
1357     case Instruction::CHECK_CAST:
1358     case Instruction::THROW:
1359     case Instruction::FILL_ARRAY_DATA:
1360     case Instruction::PACKED_SWITCH:
1361     case Instruction::SPARSE_SWITCH:
1362     case Instruction::IF_EQ:
1363     case Instruction::IF_NE:
1364     case Instruction::IF_LT:
1365     case Instruction::IF_GE:
1366     case Instruction::IF_GT:
1367     case Instruction::IF_LE:
1368     case Instruction::IF_EQZ:
1369     case Instruction::IF_NEZ:
1370     case Instruction::IF_LTZ:
1371     case Instruction::IF_GEZ:
1372     case Instruction::IF_GTZ:
1373     case Instruction::IF_LEZ:
1374     case kMirOpFusedCmplFloat:
1375     case kMirOpFusedCmpgFloat:
1376     case kMirOpFusedCmplDouble:
1377     case kMirOpFusedCmpgDouble:
1378     case kMirOpFusedCmpLong:
1379       // Nothing defined - take no action.
1380       break;
1381 
1382     case Instruction::MONITOR_ENTER:
1383       HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
1384       // NOTE: Keeping all aliasing values intact. Programs that rely on loads/stores of the
1385       // same non-volatile locations outside and inside a synchronized block being different
1386       // contain races that we cannot fix.
1387       break;
1388 
1389     case Instruction::MONITOR_EXIT:
1390       HandleNullCheck(mir, GetOperandValue(mir->ssa_rep->uses[0]));
1391       // If we're running GVN and CanModify(), uneliminated null check indicates bytecode error.
1392       if ((gvn_->GetCompilationUnit()->disable_opt & (1u << kGlobalValueNumbering)) == 0u &&
1393           gvn_->CanModify() && (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) == 0) {
1394         LOG(WARNING) << "Bytecode error: MONITOR_EXIT is still null checked at 0x" << std::hex
1395             << mir->offset << " in " << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file);
1396       }
1397       break;
1398 
1399     case Instruction::FILLED_NEW_ARRAY:
1400     case Instruction::FILLED_NEW_ARRAY_RANGE:
1401       // Nothing defined but the result will be unique and non-null.
1402       if (mir->next != nullptr && mir->next->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) {
1403         uint16_t array = MarkNonAliasingNonNull(mir->next);
1404         // Do not SetOperandValue(), we'll do that when we process the MOVE_RESULT_OBJECT.
1405         if (kLocalValueNumberingEnableFilledNewArrayTracking && mir->ssa_rep->num_uses != 0u) {
1406           AliasingValues* values = GetAliasingValues(&non_aliasing_array_value_map_, array);
1407           // Clear the value if we got a merged version in a loop.
1408           *values = AliasingValues(this);
1409           for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1410             DCHECK_EQ(High16Bits(i), 0u);
1411             uint16_t index = gvn_->LookupValue(Instruction::CONST, i, 0u, 0);
1412             uint16_t value = GetOperandValue(mir->ssa_rep->uses[i]);
1413             values->load_value_map.Put(index, value);
1414             RangeCheckKey key = { array, index };
1415             range_checked_.insert(key);
1416           }
1417         }
1418         // The MOVE_RESULT_OBJECT will be processed next and we'll return the value name then.
1419       }
1420       // All args escaped (if references).
1421       for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1422         uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
1423         HandleEscapingRef(reg);
1424       }
1425       break;
1426 
1427     case Instruction::INVOKE_DIRECT:
1428     case Instruction::INVOKE_DIRECT_RANGE:
1429     case Instruction::INVOKE_VIRTUAL:
1430     case Instruction::INVOKE_VIRTUAL_RANGE:
1431     case Instruction::INVOKE_SUPER:
1432     case Instruction::INVOKE_SUPER_RANGE:
1433     case Instruction::INVOKE_INTERFACE:
1434     case Instruction::INVOKE_INTERFACE_RANGE: {
1435         // Nothing defined but handle the null check.
1436         uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
1437         HandleNullCheck(mir, reg);
1438       }
1439       // Intentional fall-through.
1440     case Instruction::INVOKE_STATIC:
1441     case Instruction::INVOKE_STATIC_RANGE:
1442       if ((mir->optimization_flags & MIR_INLINED) == 0) {
1443         // Make ref args aliasing.
1444         for (size_t i = 0u, count = mir->ssa_rep->num_uses; i != count; ++i) {
1445           uint16_t reg = GetOperandValue(mir->ssa_rep->uses[i]);
1446           non_aliasing_refs_.erase(reg);
1447         }
1448         HandleInvokeOrClInit(mir);
1449       }
1450       break;
1451 
1452     case Instruction::MOVE_RESULT:
1453     case Instruction::MOVE_RESULT_OBJECT:
1454     case Instruction::INSTANCE_OF:
1455       // 1 result, treat as unique each time, use result s_reg - will be unique.
1456       res = GetOperandValue(mir->ssa_rep->defs[0]);
1457       SetOperandValue(mir->ssa_rep->defs[0], res);
1458       break;
1459     case Instruction::MOVE_EXCEPTION:
1460     case Instruction::NEW_INSTANCE:
1461     case Instruction::CONST_CLASS:
1462     case Instruction::NEW_ARRAY:
1463       // 1 result, treat as unique each time, use result s_reg - will be unique.
1464       res = MarkNonAliasingNonNull(mir);
1465       SetOperandValue(mir->ssa_rep->defs[0], res);
1466       break;
1467     case Instruction::CONST_STRING:
1468     case Instruction::CONST_STRING_JUMBO:
1469       // These strings are internalized, so assign value based on the string pool index.
1470       res = gvn_->LookupValue(Instruction::CONST_STRING, Low16Bits(mir->dalvikInsn.vB),
1471                               High16Bits(mir->dalvikInsn.vB), 0);
1472       SetOperandValue(mir->ssa_rep->defs[0], res);
1473       null_checked_.insert(res);  // May already be there.
1474       // NOTE: Hacking the contents of an internalized string via reflection is possible
1475       // but the behavior is undefined. Therefore, we consider the string constant and
1476       // the reference non-aliasing.
1477       // TUNING: We could keep this property even if the reference "escapes".
1478       non_aliasing_refs_.insert(res);  // May already be there.
1479       break;
1480     case Instruction::MOVE_RESULT_WIDE:
1481       // 1 wide result, treat as unique each time, use result s_reg - will be unique.
1482       res = GetOperandValueWide(mir->ssa_rep->defs[0]);
1483       SetOperandValueWide(mir->ssa_rep->defs[0], res);
1484       break;
1485 
1486     case kMirOpPhi:
1487       res = HandlePhi(mir);
1488       break;
1489 
1490     case Instruction::MOVE:
1491     case Instruction::MOVE_OBJECT:
1492     case Instruction::MOVE_16:
1493     case Instruction::MOVE_OBJECT_16:
1494     case Instruction::MOVE_FROM16:
1495     case Instruction::MOVE_OBJECT_FROM16:
1496     case kMirOpCopy:
1497       // Just copy value number of source to value number of result.
1498       res = GetOperandValue(mir->ssa_rep->uses[0]);
1499       SetOperandValue(mir->ssa_rep->defs[0], res);
1500       break;
1501 
1502     case Instruction::MOVE_WIDE:
1503     case Instruction::MOVE_WIDE_16:
1504     case Instruction::MOVE_WIDE_FROM16:
1505       // Just copy value number of source to value number of result.
1506       res = GetOperandValueWide(mir->ssa_rep->uses[0]);
1507       SetOperandValueWide(mir->ssa_rep->defs[0], res);
1508       break;
1509 
1510     case Instruction::CONST:
1511     case Instruction::CONST_4:
1512     case Instruction::CONST_16:
1513       res = gvn_->LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
1514                               High16Bits(mir->dalvikInsn.vB), 0);
1515       SetOperandValue(mir->ssa_rep->defs[0], res);
1516       break;
1517 
1518     case Instruction::CONST_HIGH16:
1519       res = gvn_->LookupValue(Instruction::CONST, 0, mir->dalvikInsn.vB, 0);
1520       SetOperandValue(mir->ssa_rep->defs[0], res);
1521       break;
1522 
1523     case Instruction::CONST_WIDE_16:
1524     case Instruction::CONST_WIDE_32: {
1525         uint16_t low_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(mir->dalvikInsn.vB),
1526                                              High16Bits(mir->dalvikInsn.vB >> 16), 1);
1527         uint16_t high_res;
1528         if (mir->dalvikInsn.vB & 0x80000000) {
1529           high_res = gvn_->LookupValue(Instruction::CONST, 0xffff, 0xffff, 2);
1530         } else {
1531           high_res = gvn_->LookupValue(Instruction::CONST, 0, 0, 2);
1532         }
1533         res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3);
1534         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1535       }
1536       break;
1537 
1538     case Instruction::CONST_WIDE: {
1539         uint32_t low_word = Low32Bits(mir->dalvikInsn.vB_wide);
1540         uint32_t high_word = High32Bits(mir->dalvikInsn.vB_wide);
1541         uint16_t low_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(low_word),
1542                                              High16Bits(low_word), 1);
1543         uint16_t high_res = gvn_->LookupValue(Instruction::CONST, Low16Bits(high_word),
1544                                               High16Bits(high_word), 2);
1545         res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3);
1546         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1547       }
1548       break;
1549 
1550     case Instruction::CONST_WIDE_HIGH16: {
1551         uint16_t low_res = gvn_->LookupValue(Instruction::CONST, 0, 0, 1);
1552         uint16_t high_res = gvn_->LookupValue(Instruction::CONST, 0,
1553                                               Low16Bits(mir->dalvikInsn.vB), 2);
1554         res = gvn_->LookupValue(Instruction::CONST, low_res, high_res, 3);
1555         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1556       }
1557       break;
1558 
1559     case Instruction::ARRAY_LENGTH: {
1560         // Handle the null check.
1561         uint16_t reg = GetOperandValue(mir->ssa_rep->uses[0]);
1562         HandleNullCheck(mir, reg);
1563       }
1564       // Intentional fall-through.
1565     case Instruction::NEG_INT:
1566     case Instruction::NOT_INT:
1567     case Instruction::NEG_FLOAT:
1568     case Instruction::INT_TO_BYTE:
1569     case Instruction::INT_TO_SHORT:
1570     case Instruction::INT_TO_CHAR:
1571     case Instruction::INT_TO_FLOAT:
1572     case Instruction::FLOAT_TO_INT: {
1573         // res = op + 1 operand
1574         uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1575         res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
1576         SetOperandValue(mir->ssa_rep->defs[0], res);
1577       }
1578       break;
1579 
1580     case Instruction::LONG_TO_FLOAT:
1581     case Instruction::LONG_TO_INT:
1582     case Instruction::DOUBLE_TO_FLOAT:
1583     case Instruction::DOUBLE_TO_INT: {
1584         // res = op + 1 wide operand
1585         uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1586         res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
1587         SetOperandValue(mir->ssa_rep->defs[0], res);
1588       }
1589       break;
1590 
1591 
1592     case Instruction::DOUBLE_TO_LONG:
1593     case Instruction::LONG_TO_DOUBLE:
1594     case Instruction::NEG_LONG:
1595     case Instruction::NOT_LONG:
1596     case Instruction::NEG_DOUBLE: {
1597         // wide res = op + 1 wide operand
1598         uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1599         res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
1600         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1601       }
1602       break;
1603 
1604     case Instruction::FLOAT_TO_DOUBLE:
1605     case Instruction::FLOAT_TO_LONG:
1606     case Instruction::INT_TO_DOUBLE:
1607     case Instruction::INT_TO_LONG: {
1608         // wide res = op + 1 operand
1609         uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1610         res = gvn_->LookupValue(opcode, operand1, kNoValue, kNoValue);
1611         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1612       }
1613       break;
1614 
1615     case Instruction::CMPL_DOUBLE:
1616     case Instruction::CMPG_DOUBLE:
1617     case Instruction::CMP_LONG: {
1618         // res = op + 2 wide operands
1619         uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1620         uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
1621         res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
1622         SetOperandValue(mir->ssa_rep->defs[0], res);
1623       }
1624       break;
1625 
1626     case Instruction::CMPG_FLOAT:
1627     case Instruction::CMPL_FLOAT:
1628     case Instruction::ADD_INT:
1629     case Instruction::ADD_INT_2ADDR:
1630     case Instruction::MUL_INT:
1631     case Instruction::MUL_INT_2ADDR:
1632     case Instruction::AND_INT:
1633     case Instruction::AND_INT_2ADDR:
1634     case Instruction::OR_INT:
1635     case Instruction::OR_INT_2ADDR:
1636     case Instruction::XOR_INT:
1637     case Instruction::XOR_INT_2ADDR:
1638     case Instruction::SUB_INT:
1639     case Instruction::SUB_INT_2ADDR:
1640     case Instruction::DIV_INT:
1641     case Instruction::DIV_INT_2ADDR:
1642     case Instruction::REM_INT:
1643     case Instruction::REM_INT_2ADDR:
1644     case Instruction::SHL_INT:
1645     case Instruction::SHL_INT_2ADDR:
1646     case Instruction::SHR_INT:
1647     case Instruction::SHR_INT_2ADDR:
1648     case Instruction::USHR_INT:
1649     case Instruction::USHR_INT_2ADDR: {
1650         // res = op + 2 operands
1651         uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1652         uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
1653         res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
1654         SetOperandValue(mir->ssa_rep->defs[0], res);
1655       }
1656       break;
1657 
1658     case Instruction::ADD_LONG:
1659     case Instruction::SUB_LONG:
1660     case Instruction::MUL_LONG:
1661     case Instruction::DIV_LONG:
1662     case Instruction::REM_LONG:
1663     case Instruction::AND_LONG:
1664     case Instruction::OR_LONG:
1665     case Instruction::XOR_LONG:
1666     case Instruction::ADD_LONG_2ADDR:
1667     case Instruction::SUB_LONG_2ADDR:
1668     case Instruction::MUL_LONG_2ADDR:
1669     case Instruction::DIV_LONG_2ADDR:
1670     case Instruction::REM_LONG_2ADDR:
1671     case Instruction::AND_LONG_2ADDR:
1672     case Instruction::OR_LONG_2ADDR:
1673     case Instruction::XOR_LONG_2ADDR:
1674     case Instruction::ADD_DOUBLE:
1675     case Instruction::SUB_DOUBLE:
1676     case Instruction::MUL_DOUBLE:
1677     case Instruction::DIV_DOUBLE:
1678     case Instruction::REM_DOUBLE:
1679     case Instruction::ADD_DOUBLE_2ADDR:
1680     case Instruction::SUB_DOUBLE_2ADDR:
1681     case Instruction::MUL_DOUBLE_2ADDR:
1682     case Instruction::DIV_DOUBLE_2ADDR:
1683     case Instruction::REM_DOUBLE_2ADDR: {
1684         // wide res = op + 2 wide operands
1685         uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1686         uint16_t operand2 = GetOperandValueWide(mir->ssa_rep->uses[2]);
1687         res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
1688         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1689       }
1690       break;
1691 
1692     case Instruction::SHL_LONG:
1693     case Instruction::SHR_LONG:
1694     case Instruction::USHR_LONG:
1695     case Instruction::SHL_LONG_2ADDR:
1696     case Instruction::SHR_LONG_2ADDR:
1697     case Instruction::USHR_LONG_2ADDR: {
1698         // wide res = op + 1 wide operand + 1 operand
1699         uint16_t operand1 = GetOperandValueWide(mir->ssa_rep->uses[0]);
1700         uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[2]);
1701         res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
1702         SetOperandValueWide(mir->ssa_rep->defs[0], res);
1703       }
1704       break;
1705 
1706     case Instruction::ADD_FLOAT:
1707     case Instruction::SUB_FLOAT:
1708     case Instruction::MUL_FLOAT:
1709     case Instruction::DIV_FLOAT:
1710     case Instruction::REM_FLOAT:
1711     case Instruction::ADD_FLOAT_2ADDR:
1712     case Instruction::SUB_FLOAT_2ADDR:
1713     case Instruction::MUL_FLOAT_2ADDR:
1714     case Instruction::DIV_FLOAT_2ADDR:
1715     case Instruction::REM_FLOAT_2ADDR: {
1716         // res = op + 2 operands
1717         uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1718         uint16_t operand2 = GetOperandValue(mir->ssa_rep->uses[1]);
1719         res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
1720         SetOperandValue(mir->ssa_rep->defs[0], res);
1721       }
1722       break;
1723 
1724     case Instruction::RSUB_INT:
1725     case Instruction::ADD_INT_LIT16:
1726     case Instruction::MUL_INT_LIT16:
1727     case Instruction::DIV_INT_LIT16:
1728     case Instruction::REM_INT_LIT16:
1729     case Instruction::AND_INT_LIT16:
1730     case Instruction::OR_INT_LIT16:
1731     case Instruction::XOR_INT_LIT16:
1732     case Instruction::ADD_INT_LIT8:
1733     case Instruction::RSUB_INT_LIT8:
1734     case Instruction::MUL_INT_LIT8:
1735     case Instruction::DIV_INT_LIT8:
1736     case Instruction::REM_INT_LIT8:
1737     case Instruction::AND_INT_LIT8:
1738     case Instruction::OR_INT_LIT8:
1739     case Instruction::XOR_INT_LIT8:
1740     case Instruction::SHL_INT_LIT8:
1741     case Instruction::SHR_INT_LIT8:
1742     case Instruction::USHR_INT_LIT8: {
1743         // Same as res = op + 2 operands, except use vC as operand 2
1744         uint16_t operand1 = GetOperandValue(mir->ssa_rep->uses[0]);
1745         uint16_t operand2 = gvn_->LookupValue(Instruction::CONST, mir->dalvikInsn.vC, 0, 0);
1746         res = gvn_->LookupValue(opcode, operand1, operand2, kNoValue);
1747         SetOperandValue(mir->ssa_rep->defs[0], res);
1748       }
1749       break;
1750 
1751     case Instruction::AGET_OBJECT:
1752     case Instruction::AGET:
1753     case Instruction::AGET_WIDE:
1754     case Instruction::AGET_BOOLEAN:
1755     case Instruction::AGET_BYTE:
1756     case Instruction::AGET_CHAR:
1757     case Instruction::AGET_SHORT:
1758       res = HandleAGet(mir, opcode);
1759       break;
1760 
1761     case Instruction::APUT_OBJECT:
1762       HandlePutObject(mir);
1763       // Intentional fall-through.
1764     case Instruction::APUT:
1765     case Instruction::APUT_WIDE:
1766     case Instruction::APUT_BYTE:
1767     case Instruction::APUT_BOOLEAN:
1768     case Instruction::APUT_SHORT:
1769     case Instruction::APUT_CHAR:
1770       HandleAPut(mir, opcode);
1771       break;
1772 
1773     case Instruction::IGET_OBJECT:
1774     case Instruction::IGET:
1775     case Instruction::IGET_WIDE:
1776     case Instruction::IGET_BOOLEAN:
1777     case Instruction::IGET_BYTE:
1778     case Instruction::IGET_CHAR:
1779     case Instruction::IGET_SHORT:
1780       res = HandleIGet(mir, opcode);
1781       break;
1782 
1783     case Instruction::IPUT_OBJECT:
1784       HandlePutObject(mir);
1785       // Intentional fall-through.
1786     case Instruction::IPUT:
1787     case Instruction::IPUT_WIDE:
1788     case Instruction::IPUT_BOOLEAN:
1789     case Instruction::IPUT_BYTE:
1790     case Instruction::IPUT_CHAR:
1791     case Instruction::IPUT_SHORT:
1792       HandleIPut(mir, opcode);
1793       break;
1794 
1795     case Instruction::SGET_OBJECT:
1796     case Instruction::SGET:
1797     case Instruction::SGET_WIDE:
1798     case Instruction::SGET_BOOLEAN:
1799     case Instruction::SGET_BYTE:
1800     case Instruction::SGET_CHAR:
1801     case Instruction::SGET_SHORT:
1802       res = HandleSGet(mir, opcode);
1803       break;
1804 
1805     case Instruction::SPUT_OBJECT:
1806       HandlePutObject(mir);
1807       // Intentional fall-through.
1808     case Instruction::SPUT:
1809     case Instruction::SPUT_WIDE:
1810     case Instruction::SPUT_BOOLEAN:
1811     case Instruction::SPUT_BYTE:
1812     case Instruction::SPUT_CHAR:
1813     case Instruction::SPUT_SHORT:
1814       HandleSPut(mir, opcode);
1815       break;
1816   }
1817   return res;
1818 }
1819 
1820 }    // namespace art
1821