blob: 7c3b7d87ced69af5c37ac4701e9b3dc0c7941e79 [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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
18#define ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_
buzbee2502e002012-12-31 16:05:53 -080019
Ian Rogers700a4022014-05-19 16:49:03 -070020#include <memory>
21
buzbee2502e002012-12-31 16:05:53 -080022#include "compiler_internals.h"
Vladimir Marko95a05972014-05-30 10:01:32 +010023#include "global_value_numbering.h"
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000024#include "utils/scoped_arena_allocator.h"
Vladimir Marko69f08ba2014-04-11 12:28:11 +010025#include "utils/scoped_arena_containers.h"
buzbee2502e002012-12-31 16:05:53 -080026
buzbee2502e002012-12-31 16:05:53 -080027namespace art {
28
Vladimir Markof59f18b2014-02-17 15:53:57 +000029class DexFile;
Vladimir Marko95a05972014-05-30 10:01:32 +010030
31// Enable/disable tracking values stored in the FILLED_NEW_ARRAY result.
32static constexpr bool kLocalValueNumberingEnableFilledNewArrayTracking = true;
buzbee2502e002012-12-31 16:05:53 -080033
buzbee311ca162013-02-28 15:56:43 -080034class LocalValueNumbering {
Vladimir Marko95a05972014-05-30 10:01:32 +010035 private:
36 static constexpr uint16_t kNoValue = GlobalValueNumbering::kNoValue;
37
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010038 public:
Vladimir Markob19955d2014-07-29 12:04:10 +010039 LocalValueNumbering(GlobalValueNumbering* gvn, BasicBlockId id, ScopedArenaAllocator* allocator);
Vladimir Marko95a05972014-05-30 10:01:32 +010040
41 BasicBlockId Id() const {
42 return id_;
43 }
44
45 bool Equals(const LocalValueNumbering& other) const;
46
Vladimir Marko95a05972014-05-30 10:01:32 +010047 bool IsValueNullChecked(uint16_t value_name) const {
48 return null_checked_.find(value_name) != null_checked_.end();
49 }
50
51 bool IsSregValue(uint16_t s_reg, uint16_t value_name) const {
52 auto it = sreg_value_map_.find(s_reg);
53 if (it != sreg_value_map_.end()) {
54 return it->second == value_name;
55 } else {
56 return gvn_->HasValue(kNoValue, s_reg, kNoValue, kNoValue, value_name);
57 }
58 }
59
60 enum MergeType {
61 kNormalMerge,
62 kCatchMerge,
63 kReturnMerge, // RETURN or PHI+RETURN. Merge only sreg maps.
64 };
65
66 void MergeOne(const LocalValueNumbering& other, MergeType merge_type);
67 void Merge(MergeType merge_type); // Merge gvn_->merge_lvns_.
Vladimir Markoa4426cf2014-10-22 17:15:53 +010068 void PrepareEntryBlock();
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010069
70 uint16_t GetValueNumber(MIR* mir);
71
72 // LocalValueNumbering should be allocated on the ArenaStack (or the native stack).
73 static void* operator new(size_t size, ScopedArenaAllocator* allocator) {
Vladimir Markob19955d2014-07-29 12:04:10 +010074 return allocator->Alloc(sizeof(LocalValueNumbering), kArenaAllocMisc);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010075 }
76
77 // Allow delete-expression to destroy a LocalValueNumbering object without deallocation.
78 static void operator delete(void* ptr) { UNUSED(ptr); }
79
Vladimir Markof59f18b2014-02-17 15:53:57 +000080 private:
Vladimir Marko95a05972014-05-30 10:01:32 +010081 // A set of value names.
82 typedef GlobalValueNumbering::ValueNameSet ValueNameSet;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010083
Vladimir Markof59f18b2014-02-17 15:53:57 +000084 // Field types correspond to the ordering of GET/PUT instructions; this order is the same
85 // for IGET, IPUT, SGET, SPUT, AGET and APUT:
86 // op 0
87 // op_WIDE 1
88 // op_OBJECT 2
89 // op_BOOLEAN 3
90 // op_BYTE 4
91 // op_CHAR 5
92 // op_SHORT 6
93 static constexpr size_t kFieldTypeCount = 7;
94
Vladimir Marko95a05972014-05-30 10:01:32 +010095 // Key is s_reg, value is value name.
96 typedef ScopedArenaSafeMap<uint16_t, uint16_t> SregValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000097
Vladimir Marko95a05972014-05-30 10:01:32 +010098 void SetOperandValueImpl(uint16_t s_reg, uint16_t value, SregValueMap* map) {
99 DCHECK_EQ(map->count(s_reg), 0u) << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file)
100 << " LVN id: " << id_ << ", s_reg: " << s_reg;
101 map->Put(s_reg, value);
102 }
103
104 uint16_t GetOperandValueImpl(int s_reg, const SregValueMap* map) const {
105 uint16_t res = kNoValue;
106 auto lb = map->find(s_reg);
107 if (lb != map->end()) {
108 res = lb->second;
109 } else {
110 // Using the original value; s_reg refers to an input reg.
111 res = gvn_->LookupValue(kNoValue, s_reg, kNoValue, kNoValue);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000112 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100113 return res;
114 }
115
116 void SetOperandValue(uint16_t s_reg, uint16_t value) {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100117 DCHECK_EQ(sreg_wide_value_map_.count(s_reg), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100118 SetOperandValueImpl(s_reg, value, &sreg_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700119 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000120
Vladimir Marko95a05972014-05-30 10:01:32 +0100121 uint16_t GetOperandValue(int s_reg) const {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100122 DCHECK_EQ(sreg_wide_value_map_.count(s_reg), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100123 return GetOperandValueImpl(s_reg, &sreg_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700124 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100125
126 void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100127 DCHECK_EQ(sreg_value_map_.count(s_reg), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100128 SetOperandValueImpl(s_reg, value, &sreg_wide_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700129 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100130
131 uint16_t GetOperandValueWide(int s_reg) const {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100132 DCHECK_EQ(sreg_value_map_.count(s_reg), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100133 return GetOperandValueImpl(s_reg, &sreg_wide_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700134 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100135
136 struct RangeCheckKey {
137 uint16_t array;
138 uint16_t index;
Vladimir Marko95a05972014-05-30 10:01:32 +0100139
140 // NOTE: Can't define this at namespace scope for a private struct.
141 bool operator==(const RangeCheckKey& other) const {
142 return array == other.array && index == other.index;
143 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100144 };
145
146 struct RangeCheckKeyComparator {
147 bool operator()(const RangeCheckKey& lhs, const RangeCheckKey& rhs) const {
148 if (lhs.array != rhs.array) {
149 return lhs.array < rhs.array;
150 }
151 return lhs.index < rhs.index;
152 }
153 };
154
155 typedef ScopedArenaSet<RangeCheckKey, RangeCheckKeyComparator> RangeCheckSet;
156
Vladimir Marko95a05972014-05-30 10:01:32 +0100157 // Maps instance field "location" (derived from base, field_id and type) to value name.
158 typedef ScopedArenaSafeMap<uint16_t, uint16_t> IFieldLocToValueMap;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100159
Vladimir Marko95a05972014-05-30 10:01:32 +0100160 // Maps static field id to value name
161 typedef ScopedArenaSafeMap<uint16_t, uint16_t> SFieldToValueMap;
162
163 struct EscapedIFieldClobberKey {
164 uint16_t base; // Or array.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000165 uint16_t type;
Vladimir Marko95a05972014-05-30 10:01:32 +0100166 uint16_t field_id; // None (kNoValue) for arrays and unresolved instance field stores.
167
168 // NOTE: Can't define this at namespace scope for a private struct.
169 bool operator==(const EscapedIFieldClobberKey& other) const {
170 return base == other.base && type == other.type && field_id == other.field_id;
171 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000172 };
173
Vladimir Marko95a05972014-05-30 10:01:32 +0100174 struct EscapedIFieldClobberKeyComparator {
175 bool operator()(const EscapedIFieldClobberKey& lhs, const EscapedIFieldClobberKey& rhs) const {
176 // Compare base first. This makes sequential iteration respect the order of base.
177 if (lhs.base != rhs.base) {
178 return lhs.base < rhs.base;
179 }
180 // Compare type second. This makes the type-clobber entries (field_id == kNoValue) last
181 // for given base and type and makes it easy to prune unnecessary entries when merging
182 // escaped_ifield_clobber_set_ from multiple LVNs.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100183 if (lhs.type != rhs.type) {
184 return lhs.type < rhs.type;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000185 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100186 return lhs.field_id < rhs.field_id;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000187 }
188 };
189
Vladimir Marko95a05972014-05-30 10:01:32 +0100190 typedef ScopedArenaSet<EscapedIFieldClobberKey, EscapedIFieldClobberKeyComparator>
191 EscapedIFieldClobberSet;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100192
Vladimir Marko95a05972014-05-30 10:01:32 +0100193 struct EscapedArrayClobberKey {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100194 uint16_t base;
195 uint16_t type;
Vladimir Marko95a05972014-05-30 10:01:32 +0100196
197 // NOTE: Can't define this at namespace scope for a private struct.
198 bool operator==(const EscapedArrayClobberKey& other) const {
199 return base == other.base && type == other.type;
200 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100201 };
202
Vladimir Marko95a05972014-05-30 10:01:32 +0100203 struct EscapedArrayClobberKeyComparator {
204 bool operator()(const EscapedArrayClobberKey& lhs, const EscapedArrayClobberKey& rhs) const {
205 // Compare base first. This makes sequential iteration respect the order of base.
206 if (lhs.base != rhs.base) {
207 return lhs.base < rhs.base;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100208 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100209 return lhs.type < rhs.type;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100210 }
211 };
212
Vladimir Marko95a05972014-05-30 10:01:32 +0100213 // Clobber set for previously non-aliasing array refs that escaped.
214 typedef ScopedArenaSet<EscapedArrayClobberKey, EscapedArrayClobberKeyComparator>
215 EscapedArrayClobberSet;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100216
Vladimir Marko95a05972014-05-30 10:01:32 +0100217 // Known location values for an aliasing set. The set can be tied to one of:
218 // 1. Instance field. The locations are aliasing references used to access the field.
219 // 2. Non-aliasing array reference. The locations are indexes to the array.
220 // 3. Aliasing array type. The locations are (reference, index) pair ids assigned by GVN.
221 // In each case we keep track of the last stored value, if any, and the set of locations
222 // where it was stored. We also keep track of all values known for the current write state
223 // (load_value_map), which can be known either because they have been loaded since the last
224 // store or because they contained the last_stored_value before the store and thus could not
225 // have changed as a result.
226 struct AliasingValues {
Vladimir Markob19955d2014-07-29 12:04:10 +0100227 explicit AliasingValues(LocalValueNumbering* lvn)
Vladimir Marko95a05972014-05-30 10:01:32 +0100228 : memory_version_before_stores(kNoValue),
229 last_stored_value(kNoValue),
Vladimir Markob19955d2014-07-29 12:04:10 +0100230 store_loc_set(std::less<uint16_t>(), lvn->null_checked_.get_allocator()),
Vladimir Marko95a05972014-05-30 10:01:32 +0100231 last_load_memory_version(kNoValue),
Vladimir Markob19955d2014-07-29 12:04:10 +0100232 load_value_map(std::less<uint16_t>(), lvn->null_checked_.get_allocator()) {
buzbee2502e002012-12-31 16:05:53 -0800233 }
buzbee2502e002012-12-31 16:05:53 -0800234
Vladimir Marko95a05972014-05-30 10:01:32 +0100235 uint16_t memory_version_before_stores; // kNoValue if start version for the field.
236 uint16_t last_stored_value; // Last stored value name, kNoValue if none.
237 ValueNameSet store_loc_set; // Where was last_stored_value stored.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100238
Vladimir Marko95a05972014-05-30 10:01:32 +0100239 // Maps refs (other than stored_to) to currently known values for this field other. On write,
240 // anything that differs from the written value is removed as it may be overwritten.
241 uint16_t last_load_memory_version; // kNoValue if not known.
242 ScopedArenaSafeMap<uint16_t, uint16_t> load_value_map;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100243
Vladimir Marko95a05972014-05-30 10:01:32 +0100244 // NOTE: Can't define this at namespace scope for a private struct.
245 bool operator==(const AliasingValues& other) const {
246 return memory_version_before_stores == other.memory_version_before_stores &&
247 last_load_memory_version == other.last_load_memory_version &&
248 last_stored_value == other.last_stored_value &&
249 store_loc_set == other.store_loc_set &&
250 load_value_map == other.load_value_map;
buzbee2502e002012-12-31 16:05:53 -0800251 }
252 };
253
Vladimir Marko95a05972014-05-30 10:01:32 +0100254 // Maps instance field id to AliasingValues, locations are object refs.
255 typedef ScopedArenaSafeMap<uint16_t, AliasingValues> AliasingIFieldValuesMap;
buzbee2502e002012-12-31 16:05:53 -0800256
Vladimir Marko95a05972014-05-30 10:01:32 +0100257 // Maps non-aliasing array reference to AliasingValues, locations are array indexes.
258 typedef ScopedArenaSafeMap<uint16_t, AliasingValues> NonAliasingArrayValuesMap;
buzbee2502e002012-12-31 16:05:53 -0800259
Vladimir Marko95a05972014-05-30 10:01:32 +0100260 // Maps aliasing array type to AliasingValues, locations are (array, index) pair ids.
261 typedef ScopedArenaSafeMap<uint16_t, AliasingValues> AliasingArrayValuesMap;
buzbee2502e002012-12-31 16:05:53 -0800262
Vladimir Marko95a05972014-05-30 10:01:32 +0100263 // Helper classes defining versions for updating and merging the AliasingValues maps above.
264 class AliasingIFieldVersions;
265 class NonAliasingArrayVersions;
266 class AliasingArrayVersions;
267
268 template <typename Map>
269 AliasingValues* GetAliasingValues(Map* map, const typename Map::key_type& key);
270
271 template <typename Versions, typename KeyType>
272 void UpdateAliasingValuesLoadVersion(const KeyType& key, AliasingValues* values);
273
274 template <typename Versions, typename Map>
275 static uint16_t AliasingValuesMergeGet(GlobalValueNumbering* gvn,
276 const LocalValueNumbering* lvn,
277 Map* map, const typename Map::key_type& key,
278 uint16_t location);
279
280 template <typename Versions, typename Map>
281 uint16_t HandleAliasingValuesGet(Map* map, const typename Map::key_type& key,
282 uint16_t location);
283
284 template <typename Versions, typename Map>
285 bool HandleAliasingValuesPut(Map* map, const typename Map::key_type& key,
286 uint16_t location, uint16_t value);
287
Vladimir Markob19955d2014-07-29 12:04:10 +0100288 template <typename K>
289 void CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
290 const ScopedArenaSafeMap<K, AliasingValues>& src);
291
Vladimir Markof59f18b2014-02-17 15:53:57 +0000292 uint16_t MarkNonAliasingNonNull(MIR* mir);
Vladimir Marko95a05972014-05-30 10:01:32 +0100293 bool IsNonAliasing(uint16_t reg) const;
294 bool IsNonAliasingIField(uint16_t reg, uint16_t field_id, uint16_t type) const;
295 bool IsNonAliasingArray(uint16_t reg, uint16_t type) const;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000296 void HandleNullCheck(MIR* mir, uint16_t reg);
297 void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
298 void HandlePutObject(MIR* mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100299 void HandleEscapingRef(uint16_t base);
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100300 void HandleInvokeArgs(const MIR* mir, const LocalValueNumbering* mir_lvn);
Vladimir Marko95a05972014-05-30 10:01:32 +0100301 uint16_t HandlePhi(MIR* mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100302 uint16_t HandleAGet(MIR* mir, uint16_t opcode);
303 void HandleAPut(MIR* mir, uint16_t opcode);
304 uint16_t HandleIGet(MIR* mir, uint16_t opcode);
305 void HandleIPut(MIR* mir, uint16_t opcode);
306 uint16_t HandleSGet(MIR* mir, uint16_t opcode);
307 void HandleSPut(MIR* mir, uint16_t opcode);
Vladimir Marko95a05972014-05-30 10:01:32 +0100308 void RemoveSFieldsForType(uint16_t type);
Vladimir Markofa236452014-09-29 17:58:10 +0100309 void HandleInvokeOrClInitOrAcquireOp(MIR* mir);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000310
Vladimir Marko95a05972014-05-30 10:01:32 +0100311 bool SameMemoryVersion(const LocalValueNumbering& other) const;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100312
Vladimir Marko95a05972014-05-30 10:01:32 +0100313 uint16_t NewMemoryVersion(uint16_t* new_version);
314 void MergeMemoryVersions(bool clobbered_catch);
315
316 void PruneNonAliasingRefsForCatch();
317
318 template <typename Set, Set LocalValueNumbering::* set_ptr>
319 void IntersectSets();
320
Vladimir Markob19955d2014-07-29 12:04:10 +0100321 void CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src);
322
Vladimir Marko95a05972014-05-30 10:01:32 +0100323 // Intersect maps as sets. The value type must be equality-comparable.
Vladimir Markob19955d2014-07-29 12:04:10 +0100324 template <SregValueMap LocalValueNumbering::* map_ptr>
325 void IntersectSregValueMaps();
Vladimir Marko95a05972014-05-30 10:01:32 +0100326
327 // Intersect maps as sets. The value type must be equality-comparable.
328 template <typename Map>
329 static void InPlaceIntersectMaps(Map* work_map, const Map& other_map);
330
331 template <typename Set, Set LocalValueNumbering::*set_ptr, void (LocalValueNumbering::*MergeFn)(
332 const typename Set::value_type& entry, typename Set::iterator hint)>
333 void MergeSets();
334
335 void IntersectAliasingValueLocations(AliasingValues* work_values, const AliasingValues* values);
336
337 void MergeEscapedRefs(const ValueNameSet::value_type& entry, ValueNameSet::iterator hint);
338 void MergeEscapedIFieldTypeClobberSets(const EscapedIFieldClobberSet::value_type& entry,
339 EscapedIFieldClobberSet::iterator hint);
340 void MergeEscapedIFieldClobberSets(const EscapedIFieldClobberSet::value_type& entry,
341 EscapedIFieldClobberSet::iterator hint);
342 void MergeEscapedArrayClobberSets(const EscapedArrayClobberSet::value_type& entry,
343 EscapedArrayClobberSet::iterator hint);
Vladimir Marko95a05972014-05-30 10:01:32 +0100344 void MergeSFieldValues(const SFieldToValueMap::value_type& entry,
345 SFieldToValueMap::iterator hint);
346 void MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type& entry,
347 IFieldLocToValueMap::iterator hint);
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100348 void MergeNullChecked();
Vladimir Marko95a05972014-05-30 10:01:32 +0100349
350 template <typename Map, Map LocalValueNumbering::*map_ptr, typename Versions>
351 void MergeAliasingValues(const typename Map::value_type& entry, typename Map::iterator hint);
352
353 GlobalValueNumbering* gvn_;
354
355 // We're using the block id as a 16-bit operand value for some lookups.
Andreas Gampe785d2f22014-11-03 22:57:30 -0800356 static_assert(sizeof(BasicBlockId) == sizeof(uint16_t), "BasicBlockId must be 16 bit");
Vladimir Marko95a05972014-05-30 10:01:32 +0100357 BasicBlockId id_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100358
buzbee2502e002012-12-31 16:05:53 -0800359 SregValueMap sreg_value_map_;
360 SregValueMap sreg_wide_value_map_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100361
362 SFieldToValueMap sfield_value_map_;
363 IFieldLocToValueMap non_aliasing_ifield_value_map_;
364 AliasingIFieldValuesMap aliasing_ifield_value_map_;
365 NonAliasingArrayValuesMap non_aliasing_array_value_map_;
366 AliasingArrayValuesMap aliasing_array_value_map_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100367
368 // Data for dealing with memory clobbering and store/load aliasing.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000369 uint16_t global_memory_version_;
370 uint16_t unresolved_sfield_version_[kFieldTypeCount];
371 uint16_t unresolved_ifield_version_[kFieldTypeCount];
Vladimir Markof59f18b2014-02-17 15:53:57 +0000372 // Value names of references to objects that cannot be reached through a different value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000373 ValueNameSet non_aliasing_refs_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100374 // Previously non-aliasing refs that escaped but can still be used for non-aliasing AGET/IGET.
375 ValueNameSet escaped_refs_;
376 // Blacklists for cases where escaped_refs_ can't be used.
377 EscapedIFieldClobberSet escaped_ifield_clobber_set_;
378 EscapedArrayClobberSet escaped_array_clobber_set_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100379
380 // Range check and null check elimination.
381 RangeCheckSet range_checked_;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000382 ValueNameSet null_checked_;
383
Vladimir Marko95a05972014-05-30 10:01:32 +0100384 // Reuse one vector for all merges to avoid leaking too much memory on the ArenaStack.
385 ScopedArenaVector<BasicBlockId> merge_names_;
386 // Map to identify when different locations merge the same values.
387 ScopedArenaSafeMap<ScopedArenaVector<BasicBlockId>, uint16_t> merge_map_;
388 // New memory version for merge, kNoValue if all memory versions matched.
389 uint16_t merge_new_memory_version_;
390
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000391 DISALLOW_COPY_AND_ASSIGN(LocalValueNumbering);
buzbee2502e002012-12-31 16:05:53 -0800392};
393
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700394} // namespace art
buzbee2502e002012-12-31 16:05:53 -0800395
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700396#endif // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_