blob: 8613f97e3894b4d29250e44a997eaa8e13345dc5 [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"
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070024#include "utils/arena_object.h"
buzbee2502e002012-12-31 16:05:53 -080025
buzbee2502e002012-12-31 16:05:53 -080026namespace art {
27
Vladimir Markof59f18b2014-02-17 15:53:57 +000028class DexFile;
Vladimir Marko95a05972014-05-30 10:01:32 +010029
30// Enable/disable tracking values stored in the FILLED_NEW_ARRAY result.
31static constexpr bool kLocalValueNumberingEnableFilledNewArrayTracking = true;
buzbee2502e002012-12-31 16:05:53 -080032
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070033class LocalValueNumbering : public DeletableArenaObject<kArenaAllocMisc> {
Vladimir Marko95a05972014-05-30 10:01:32 +010034 private:
35 static constexpr uint16_t kNoValue = GlobalValueNumbering::kNoValue;
36
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010037 public:
Vladimir Markob19955d2014-07-29 12:04:10 +010038 LocalValueNumbering(GlobalValueNumbering* gvn, BasicBlockId id, ScopedArenaAllocator* allocator);
Vladimir Marko95a05972014-05-30 10:01:32 +010039
40 BasicBlockId Id() const {
41 return id_;
42 }
43
44 bool Equals(const LocalValueNumbering& other) const;
45
Vladimir Marko95a05972014-05-30 10:01:32 +010046 bool IsValueNullChecked(uint16_t value_name) const {
47 return null_checked_.find(value_name) != null_checked_.end();
48 }
49
Razvan A Lupusorue0951142014-11-14 14:36:55 -080050 bool IsValueDivZeroChecked(uint16_t value_name) const {
51 return div_zero_checked_.find(value_name) != div_zero_checked_.end();
52 }
53
Vladimir Marko95a05972014-05-30 10:01:32 +010054 bool IsSregValue(uint16_t s_reg, uint16_t value_name) const {
55 auto it = sreg_value_map_.find(s_reg);
56 if (it != sreg_value_map_.end()) {
57 return it->second == value_name;
58 } else {
59 return gvn_->HasValue(kNoValue, s_reg, kNoValue, kNoValue, value_name);
60 }
61 }
62
63 enum MergeType {
64 kNormalMerge,
65 kCatchMerge,
66 kReturnMerge, // RETURN or PHI+RETURN. Merge only sreg maps.
67 };
68
69 void MergeOne(const LocalValueNumbering& other, MergeType merge_type);
70 void Merge(MergeType merge_type); // Merge gvn_->merge_lvns_.
Vladimir Markoa4426cf2014-10-22 17:15:53 +010071 void PrepareEntryBlock();
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010072
73 uint16_t GetValueNumber(MIR* mir);
74
Vladimir Markof59f18b2014-02-17 15:53:57 +000075 private:
Vladimir Marko95a05972014-05-30 10:01:32 +010076 // A set of value names.
77 typedef GlobalValueNumbering::ValueNameSet ValueNameSet;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +010078
Vladimir Markof59f18b2014-02-17 15:53:57 +000079 // Field types correspond to the ordering of GET/PUT instructions; this order is the same
80 // for IGET, IPUT, SGET, SPUT, AGET and APUT:
81 // op 0
82 // op_WIDE 1
83 // op_OBJECT 2
84 // op_BOOLEAN 3
85 // op_BYTE 4
86 // op_CHAR 5
87 // op_SHORT 6
88 static constexpr size_t kFieldTypeCount = 7;
89
Vladimir Marko95a05972014-05-30 10:01:32 +010090 // Key is s_reg, value is value name.
91 typedef ScopedArenaSafeMap<uint16_t, uint16_t> SregValueMap;
Vladimir Markof59f18b2014-02-17 15:53:57 +000092
Vladimir Marko95a05972014-05-30 10:01:32 +010093 void SetOperandValueImpl(uint16_t s_reg, uint16_t value, SregValueMap* map) {
94 DCHECK_EQ(map->count(s_reg), 0u) << PrettyMethod(gvn_->cu_->method_idx, *gvn_->cu_->dex_file)
95 << " LVN id: " << id_ << ", s_reg: " << s_reg;
96 map->Put(s_reg, value);
97 }
98
99 uint16_t GetOperandValueImpl(int s_reg, const SregValueMap* map) const {
100 uint16_t res = kNoValue;
101 auto lb = map->find(s_reg);
102 if (lb != map->end()) {
103 res = lb->second;
104 } else {
105 // Using the original value; s_reg refers to an input reg.
106 res = gvn_->LookupValue(kNoValue, s_reg, kNoValue, kNoValue);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000107 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100108 return res;
109 }
110
111 void SetOperandValue(uint16_t s_reg, uint16_t value) {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100112 DCHECK_EQ(sreg_wide_value_map_.count(s_reg), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100113 SetOperandValueImpl(s_reg, value, &sreg_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700114 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000115
Vladimir Marko95a05972014-05-30 10:01:32 +0100116 uint16_t GetOperandValue(int s_reg) const {
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 return GetOperandValueImpl(s_reg, &sreg_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700119 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100120
121 void SetOperandValueWide(uint16_t s_reg, uint16_t value) {
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100122 DCHECK_EQ(sreg_value_map_.count(s_reg), 0u);
Vladimir Marko95a05972014-05-30 10:01:32 +0100123 SetOperandValueImpl(s_reg, value, &sreg_wide_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700124 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100125
126 uint16_t GetOperandValueWide(int s_reg) const {
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 return GetOperandValueImpl(s_reg, &sreg_wide_value_map_);
Andreas Gampec8ccf682014-09-29 20:07:43 -0700129 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100130
131 struct RangeCheckKey {
132 uint16_t array;
133 uint16_t index;
Vladimir Marko95a05972014-05-30 10:01:32 +0100134
135 // NOTE: Can't define this at namespace scope for a private struct.
136 bool operator==(const RangeCheckKey& other) const {
137 return array == other.array && index == other.index;
138 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100139 };
140
141 struct RangeCheckKeyComparator {
142 bool operator()(const RangeCheckKey& lhs, const RangeCheckKey& rhs) const {
143 if (lhs.array != rhs.array) {
144 return lhs.array < rhs.array;
145 }
146 return lhs.index < rhs.index;
147 }
148 };
149
150 typedef ScopedArenaSet<RangeCheckKey, RangeCheckKeyComparator> RangeCheckSet;
151
Vladimir Marko95a05972014-05-30 10:01:32 +0100152 // Maps instance field "location" (derived from base, field_id and type) to value name.
153 typedef ScopedArenaSafeMap<uint16_t, uint16_t> IFieldLocToValueMap;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100154
Vladimir Marko95a05972014-05-30 10:01:32 +0100155 // Maps static field id to value name
156 typedef ScopedArenaSafeMap<uint16_t, uint16_t> SFieldToValueMap;
157
158 struct EscapedIFieldClobberKey {
159 uint16_t base; // Or array.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000160 uint16_t type;
Vladimir Marko95a05972014-05-30 10:01:32 +0100161 uint16_t field_id; // None (kNoValue) for arrays and unresolved instance field stores.
162
163 // NOTE: Can't define this at namespace scope for a private struct.
164 bool operator==(const EscapedIFieldClobberKey& other) const {
165 return base == other.base && type == other.type && field_id == other.field_id;
166 }
Vladimir Markof59f18b2014-02-17 15:53:57 +0000167 };
168
Vladimir Marko95a05972014-05-30 10:01:32 +0100169 struct EscapedIFieldClobberKeyComparator {
170 bool operator()(const EscapedIFieldClobberKey& lhs, const EscapedIFieldClobberKey& rhs) const {
171 // Compare base first. This makes sequential iteration respect the order of base.
172 if (lhs.base != rhs.base) {
173 return lhs.base < rhs.base;
174 }
175 // Compare type second. This makes the type-clobber entries (field_id == kNoValue) last
176 // for given base and type and makes it easy to prune unnecessary entries when merging
177 // escaped_ifield_clobber_set_ from multiple LVNs.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100178 if (lhs.type != rhs.type) {
179 return lhs.type < rhs.type;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000180 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100181 return lhs.field_id < rhs.field_id;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000182 }
183 };
184
Vladimir Marko95a05972014-05-30 10:01:32 +0100185 typedef ScopedArenaSet<EscapedIFieldClobberKey, EscapedIFieldClobberKeyComparator>
186 EscapedIFieldClobberSet;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100187
Vladimir Marko95a05972014-05-30 10:01:32 +0100188 struct EscapedArrayClobberKey {
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100189 uint16_t base;
190 uint16_t type;
Vladimir Marko95a05972014-05-30 10:01:32 +0100191
192 // NOTE: Can't define this at namespace scope for a private struct.
193 bool operator==(const EscapedArrayClobberKey& other) const {
194 return base == other.base && type == other.type;
195 }
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100196 };
197
Vladimir Marko95a05972014-05-30 10:01:32 +0100198 struct EscapedArrayClobberKeyComparator {
199 bool operator()(const EscapedArrayClobberKey& lhs, const EscapedArrayClobberKey& rhs) const {
200 // Compare base first. This makes sequential iteration respect the order of base.
201 if (lhs.base != rhs.base) {
202 return lhs.base < rhs.base;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100203 }
Vladimir Marko95a05972014-05-30 10:01:32 +0100204 return lhs.type < rhs.type;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100205 }
206 };
207
Vladimir Marko95a05972014-05-30 10:01:32 +0100208 // Clobber set for previously non-aliasing array refs that escaped.
209 typedef ScopedArenaSet<EscapedArrayClobberKey, EscapedArrayClobberKeyComparator>
210 EscapedArrayClobberSet;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100211
Vladimir Marko95a05972014-05-30 10:01:32 +0100212 // Known location values for an aliasing set. The set can be tied to one of:
213 // 1. Instance field. The locations are aliasing references used to access the field.
214 // 2. Non-aliasing array reference. The locations are indexes to the array.
215 // 3. Aliasing array type. The locations are (reference, index) pair ids assigned by GVN.
216 // In each case we keep track of the last stored value, if any, and the set of locations
217 // where it was stored. We also keep track of all values known for the current write state
218 // (load_value_map), which can be known either because they have been loaded since the last
219 // store or because they contained the last_stored_value before the store and thus could not
220 // have changed as a result.
221 struct AliasingValues {
Vladimir Markob19955d2014-07-29 12:04:10 +0100222 explicit AliasingValues(LocalValueNumbering* lvn)
Vladimir Marko95a05972014-05-30 10:01:32 +0100223 : memory_version_before_stores(kNoValue),
224 last_stored_value(kNoValue),
Vladimir Markob19955d2014-07-29 12:04:10 +0100225 store_loc_set(std::less<uint16_t>(), lvn->null_checked_.get_allocator()),
Vladimir Marko95a05972014-05-30 10:01:32 +0100226 last_load_memory_version(kNoValue),
Vladimir Markob19955d2014-07-29 12:04:10 +0100227 load_value_map(std::less<uint16_t>(), lvn->null_checked_.get_allocator()) {
buzbee2502e002012-12-31 16:05:53 -0800228 }
buzbee2502e002012-12-31 16:05:53 -0800229
Vladimir Marko95a05972014-05-30 10:01:32 +0100230 uint16_t memory_version_before_stores; // kNoValue if start version for the field.
231 uint16_t last_stored_value; // Last stored value name, kNoValue if none.
232 ValueNameSet store_loc_set; // Where was last_stored_value stored.
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100233
Vladimir Marko95a05972014-05-30 10:01:32 +0100234 // Maps refs (other than stored_to) to currently known values for this field other. On write,
235 // anything that differs from the written value is removed as it may be overwritten.
236 uint16_t last_load_memory_version; // kNoValue if not known.
237 ScopedArenaSafeMap<uint16_t, uint16_t> load_value_map;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100238
Vladimir Marko95a05972014-05-30 10:01:32 +0100239 // NOTE: Can't define this at namespace scope for a private struct.
240 bool operator==(const AliasingValues& other) const {
241 return memory_version_before_stores == other.memory_version_before_stores &&
242 last_load_memory_version == other.last_load_memory_version &&
243 last_stored_value == other.last_stored_value &&
244 store_loc_set == other.store_loc_set &&
245 load_value_map == other.load_value_map;
buzbee2502e002012-12-31 16:05:53 -0800246 }
247 };
248
Vladimir Marko95a05972014-05-30 10:01:32 +0100249 // Maps instance field id to AliasingValues, locations are object refs.
250 typedef ScopedArenaSafeMap<uint16_t, AliasingValues> AliasingIFieldValuesMap;
buzbee2502e002012-12-31 16:05:53 -0800251
Vladimir Marko95a05972014-05-30 10:01:32 +0100252 // Maps non-aliasing array reference to AliasingValues, locations are array indexes.
253 typedef ScopedArenaSafeMap<uint16_t, AliasingValues> NonAliasingArrayValuesMap;
buzbee2502e002012-12-31 16:05:53 -0800254
Vladimir Marko95a05972014-05-30 10:01:32 +0100255 // Maps aliasing array type to AliasingValues, locations are (array, index) pair ids.
256 typedef ScopedArenaSafeMap<uint16_t, AliasingValues> AliasingArrayValuesMap;
buzbee2502e002012-12-31 16:05:53 -0800257
Vladimir Marko95a05972014-05-30 10:01:32 +0100258 // Helper classes defining versions for updating and merging the AliasingValues maps above.
259 class AliasingIFieldVersions;
260 class NonAliasingArrayVersions;
261 class AliasingArrayVersions;
262
263 template <typename Map>
264 AliasingValues* GetAliasingValues(Map* map, const typename Map::key_type& key);
265
266 template <typename Versions, typename KeyType>
267 void UpdateAliasingValuesLoadVersion(const KeyType& key, AliasingValues* values);
268
269 template <typename Versions, typename Map>
270 static uint16_t AliasingValuesMergeGet(GlobalValueNumbering* gvn,
271 const LocalValueNumbering* lvn,
272 Map* map, const typename Map::key_type& key,
273 uint16_t location);
274
275 template <typename Versions, typename Map>
276 uint16_t HandleAliasingValuesGet(Map* map, const typename Map::key_type& key,
277 uint16_t location);
278
279 template <typename Versions, typename Map>
280 bool HandleAliasingValuesPut(Map* map, const typename Map::key_type& key,
281 uint16_t location, uint16_t value);
282
Vladimir Markob19955d2014-07-29 12:04:10 +0100283 template <typename K>
284 void CopyAliasingValuesMap(ScopedArenaSafeMap<K, AliasingValues>* dest,
285 const ScopedArenaSafeMap<K, AliasingValues>& src);
286
Vladimir Markof59f18b2014-02-17 15:53:57 +0000287 uint16_t MarkNonAliasingNonNull(MIR* mir);
Vladimir Marko95a05972014-05-30 10:01:32 +0100288 bool IsNonAliasing(uint16_t reg) const;
289 bool IsNonAliasingIField(uint16_t reg, uint16_t field_id, uint16_t type) const;
290 bool IsNonAliasingArray(uint16_t reg, uint16_t type) const;
Vladimir Markof59f18b2014-02-17 15:53:57 +0000291 void HandleNullCheck(MIR* mir, uint16_t reg);
292 void HandleRangeCheck(MIR* mir, uint16_t array, uint16_t index);
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800293 void HandleDivZeroCheck(MIR* mir, uint16_t reg);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000294 void HandlePutObject(MIR* mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100295 void HandleEscapingRef(uint16_t base);
Vladimir Markoa4426cf2014-10-22 17:15:53 +0100296 void HandleInvokeArgs(const MIR* mir, const LocalValueNumbering* mir_lvn);
Vladimir Marko95a05972014-05-30 10:01:32 +0100297 uint16_t HandlePhi(MIR* mir);
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100298 uint16_t HandleAGet(MIR* mir, uint16_t opcode);
299 void HandleAPut(MIR* mir, uint16_t opcode);
300 uint16_t HandleIGet(MIR* mir, uint16_t opcode);
301 void HandleIPut(MIR* mir, uint16_t opcode);
302 uint16_t HandleSGet(MIR* mir, uint16_t opcode);
303 void HandleSPut(MIR* mir, uint16_t opcode);
Vladimir Marko95a05972014-05-30 10:01:32 +0100304 void RemoveSFieldsForType(uint16_t type);
Vladimir Markofa236452014-09-29 17:58:10 +0100305 void HandleInvokeOrClInitOrAcquireOp(MIR* mir);
Vladimir Markof59f18b2014-02-17 15:53:57 +0000306
Vladimir Marko95a05972014-05-30 10:01:32 +0100307 bool SameMemoryVersion(const LocalValueNumbering& other) const;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100308
Vladimir Marko95a05972014-05-30 10:01:32 +0100309 uint16_t NewMemoryVersion(uint16_t* new_version);
310 void MergeMemoryVersions(bool clobbered_catch);
311
312 void PruneNonAliasingRefsForCatch();
313
314 template <typename Set, Set LocalValueNumbering::* set_ptr>
315 void IntersectSets();
316
Vladimir Markob19955d2014-07-29 12:04:10 +0100317 void CopyLiveSregValues(SregValueMap* dest, const SregValueMap& src);
318
Vladimir Marko95a05972014-05-30 10:01:32 +0100319 // Intersect maps as sets. The value type must be equality-comparable.
Vladimir Markob19955d2014-07-29 12:04:10 +0100320 template <SregValueMap LocalValueNumbering::* map_ptr>
321 void IntersectSregValueMaps();
Vladimir Marko95a05972014-05-30 10:01:32 +0100322
323 // Intersect maps as sets. The value type must be equality-comparable.
324 template <typename Map>
325 static void InPlaceIntersectMaps(Map* work_map, const Map& other_map);
326
327 template <typename Set, Set LocalValueNumbering::*set_ptr, void (LocalValueNumbering::*MergeFn)(
328 const typename Set::value_type& entry, typename Set::iterator hint)>
329 void MergeSets();
330
331 void IntersectAliasingValueLocations(AliasingValues* work_values, const AliasingValues* values);
332
333 void MergeEscapedRefs(const ValueNameSet::value_type& entry, ValueNameSet::iterator hint);
334 void MergeEscapedIFieldTypeClobberSets(const EscapedIFieldClobberSet::value_type& entry,
335 EscapedIFieldClobberSet::iterator hint);
336 void MergeEscapedIFieldClobberSets(const EscapedIFieldClobberSet::value_type& entry,
337 EscapedIFieldClobberSet::iterator hint);
338 void MergeEscapedArrayClobberSets(const EscapedArrayClobberSet::value_type& entry,
339 EscapedArrayClobberSet::iterator hint);
Vladimir Marko95a05972014-05-30 10:01:32 +0100340 void MergeSFieldValues(const SFieldToValueMap::value_type& entry,
341 SFieldToValueMap::iterator hint);
342 void MergeNonAliasingIFieldValues(const IFieldLocToValueMap::value_type& entry,
343 IFieldLocToValueMap::iterator hint);
Vladimir Marko2d2365c2014-08-19 18:08:39 +0100344 void MergeNullChecked();
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800345 void MergeDivZeroChecked();
Vladimir Marko95a05972014-05-30 10:01:32 +0100346
347 template <typename Map, Map LocalValueNumbering::*map_ptr, typename Versions>
348 void MergeAliasingValues(const typename Map::value_type& entry, typename Map::iterator hint);
349
350 GlobalValueNumbering* gvn_;
351
352 // We're using the block id as a 16-bit operand value for some lookups.
Andreas Gampe785d2f22014-11-03 22:57:30 -0800353 static_assert(sizeof(BasicBlockId) == sizeof(uint16_t), "BasicBlockId must be 16 bit");
Vladimir Marko95a05972014-05-30 10:01:32 +0100354 BasicBlockId id_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100355
buzbee2502e002012-12-31 16:05:53 -0800356 SregValueMap sreg_value_map_;
357 SregValueMap sreg_wide_value_map_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100358
359 SFieldToValueMap sfield_value_map_;
360 IFieldLocToValueMap non_aliasing_ifield_value_map_;
361 AliasingIFieldValuesMap aliasing_ifield_value_map_;
362 NonAliasingArrayValuesMap non_aliasing_array_value_map_;
363 AliasingArrayValuesMap aliasing_array_value_map_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100364
365 // Data for dealing with memory clobbering and store/load aliasing.
Vladimir Markof59f18b2014-02-17 15:53:57 +0000366 uint16_t global_memory_version_;
367 uint16_t unresolved_sfield_version_[kFieldTypeCount];
368 uint16_t unresolved_ifield_version_[kFieldTypeCount];
Vladimir Markof59f18b2014-02-17 15:53:57 +0000369 // Value names of references to objects that cannot be reached through a different value name.
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000370 ValueNameSet non_aliasing_refs_;
Vladimir Marko95a05972014-05-30 10:01:32 +0100371 // Previously non-aliasing refs that escaped but can still be used for non-aliasing AGET/IGET.
372 ValueNameSet escaped_refs_;
373 // Blacklists for cases where escaped_refs_ can't be used.
374 EscapedIFieldClobberSet escaped_ifield_clobber_set_;
375 EscapedArrayClobberSet escaped_array_clobber_set_;
Vladimir Marko2ac01fc2014-05-22 12:09:08 +0100376
377 // Range check and null check elimination.
378 RangeCheckSet range_checked_;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000379 ValueNameSet null_checked_;
Razvan A Lupusorue0951142014-11-14 14:36:55 -0800380 ValueNameSet div_zero_checked_;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000381
Vladimir Marko95a05972014-05-30 10:01:32 +0100382 // Reuse one vector for all merges to avoid leaking too much memory on the ArenaStack.
383 ScopedArenaVector<BasicBlockId> merge_names_;
384 // Map to identify when different locations merge the same values.
385 ScopedArenaSafeMap<ScopedArenaVector<BasicBlockId>, uint16_t> merge_map_;
386 // New memory version for merge, kNoValue if all memory versions matched.
387 uint16_t merge_new_memory_version_;
388
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000389 DISALLOW_COPY_AND_ASSIGN(LocalValueNumbering);
buzbee2502e002012-12-31 16:05:53 -0800390};
391
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700392} // namespace art
buzbee2502e002012-12-31 16:05:53 -0800393
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700394#endif // ART_COMPILER_DEX_LOCAL_VALUE_NUMBERING_H_