blob: 882fe28cc7b01f5508814a36cb398b33c7b53107 [file] [log] [blame]
xueliang.zhongc239a2b2017-04-27 15:31:37 +01001/*
2 * Copyright (C) 2017 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#ifndef ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_
18#define ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_
19
Vladimir Markoef898422020-06-08 10:26:06 +010020#include "base/bit_vector-inl.h"
21#include "base/scoped_arena_containers.h"
xueliang.zhongc239a2b2017-04-27 15:31:37 +010022#include "escape.h"
23#include "nodes.h"
24#include "optimization.h"
25
Vladimir Marko0a516052019-10-14 13:00:44 +000026namespace art {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010027
28// A ReferenceInfo contains additional info about a reference such as
29// whether it's a singleton, returned, etc.
Vladimir Marko009d1662017-10-10 13:21:15 +010030class ReferenceInfo : public ArenaObject<kArenaAllocLSA> {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010031 public:
32 ReferenceInfo(HInstruction* reference, size_t pos)
33 : reference_(reference),
34 position_(pos),
35 is_singleton_(true),
36 is_singleton_and_not_returned_(true),
Mingyao Yang0e3151b2017-10-30 11:19:57 -070037 is_singleton_and_not_deopt_visible_(true) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010038 CalculateEscape(reference_,
39 nullptr,
40 &is_singleton_,
41 &is_singleton_and_not_returned_,
42 &is_singleton_and_not_deopt_visible_);
43 }
44
45 HInstruction* GetReference() const {
46 return reference_;
47 }
48
49 size_t GetPosition() const {
50 return position_;
51 }
52
53 // Returns true if reference_ is the only name that can refer to its value during
54 // the lifetime of the method. So it's guaranteed to not have any alias in
55 // the method (including its callees).
56 bool IsSingleton() const {
57 return is_singleton_;
58 }
59
60 // Returns true if reference_ is a singleton and not returned to the caller or
61 // used as an environment local of an HDeoptimize instruction.
62 // The allocation and stores into reference_ may be eliminated for such cases.
63 bool IsSingletonAndRemovable() const {
64 return is_singleton_and_not_returned_ && is_singleton_and_not_deopt_visible_;
65 }
66
67 // Returns true if reference_ is a singleton and returned to the caller or
68 // used as an environment local of an HDeoptimize instruction.
69 bool IsSingletonAndNonRemovable() const {
70 return is_singleton_ &&
71 (!is_singleton_and_not_returned_ || !is_singleton_and_not_deopt_visible_);
72 }
73
xueliang.zhongc239a2b2017-04-27 15:31:37 +010074 private:
75 HInstruction* const reference_;
76 const size_t position_; // position in HeapLocationCollector's ref_info_array_.
77
78 // Can only be referred to by a single name in the method.
79 bool is_singleton_;
80 // Is singleton and not returned to caller.
81 bool is_singleton_and_not_returned_;
82 // Is singleton and not used as an environment local of HDeoptimize.
83 bool is_singleton_and_not_deopt_visible_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +010084
85 DISALLOW_COPY_AND_ASSIGN(ReferenceInfo);
86};
87
88// A heap location is a reference-offset/index pair that a value can be loaded from
89// or stored to.
Vladimir Marko009d1662017-10-10 13:21:15 +010090class HeapLocation : public ArenaObject<kArenaAllocLSA> {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010091 public:
92 static constexpr size_t kInvalidFieldOffset = -1;
xueliang.zhongb50b16a2017-09-19 17:43:29 +010093 // Default value for heap locations which are not vector data.
94 static constexpr size_t kScalar = 1;
xueliang.zhongc239a2b2017-04-27 15:31:37 +010095 // TODO: more fine-grained array types.
96 static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
97
98 HeapLocation(ReferenceInfo* ref_info,
Aart Bikb765a3f2018-05-10 14:47:48 -070099 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100100 size_t offset,
101 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100102 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100103 int16_t declaring_class_def_index)
104 : ref_info_(ref_info),
Aart Bikb765a3f2018-05-10 14:47:48 -0700105 type_(DataType::ToSigned(type)),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100106 offset_(offset),
107 index_(index),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100108 vector_length_(vector_length),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100109 declaring_class_def_index_(declaring_class_def_index),
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700110 has_aliased_locations_(false) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100111 DCHECK(ref_info != nullptr);
112 DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
113 (offset != kInvalidFieldOffset && index == nullptr));
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100114 }
115
116 ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
Aart Bikb765a3f2018-05-10 14:47:48 -0700117 DataType::Type GetType() const { return type_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100118 size_t GetOffset() const { return offset_; }
119 HInstruction* GetIndex() const { return index_; }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100120 size_t GetVectorLength() const { return vector_length_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100121
122 // Returns the definition of declaring class' dex index.
123 // It's kDeclaringClassDefIndexForArrays for an array element.
124 int16_t GetDeclaringClassDefIndex() const {
125 return declaring_class_def_index_;
126 }
127
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100128 bool IsArray() const {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100129 return index_ != nullptr;
130 }
131
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700132 bool HasAliasedLocations() const {
133 return has_aliased_locations_;
134 }
135
136 void SetHasAliasedLocations(bool val) {
137 has_aliased_locations_ = val;
138 }
139
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100140 private:
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100141 // Reference for instance/static field, array element or vector data.
142 ReferenceInfo* const ref_info_;
Aart Bikb765a3f2018-05-10 14:47:48 -0700143 // Type of data residing at HeapLocation (always signed for integral
144 // data since e.g. a[i] and a[i] & 0xff are represented by differently
145 // signed types; char vs short are disambiguated through the reference).
146 const DataType::Type type_;
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100147 // Offset of static/instance field.
148 // Invalid when this HeapLocation is not field.
149 const size_t offset_;
150 // Index of an array element or starting index of vector data.
151 // Invalid when this HeapLocation is not array.
152 HInstruction* const index_;
153 // Vector length of vector data.
154 // When this HeapLocation is not vector data, it's value is kScalar.
155 const size_t vector_length_;
156 // Declaring class's def's dex index.
157 // Invalid when this HeapLocation is not field access.
158 const int16_t declaring_class_def_index_;
159
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700160 // Has aliased heap locations in the method, due to either the
161 // reference is aliased or the array element is aliased via different
162 // index names.
163 bool has_aliased_locations_;
164
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100165 DISALLOW_COPY_AND_ASSIGN(HeapLocation);
166};
167
168// A HeapLocationCollector collects all relevant heap locations and keeps
169// an aliasing matrix for all locations.
170class HeapLocationCollector : public HGraphVisitor {
171 public:
172 static constexpr size_t kHeapLocationNotFound = -1;
173 // Start with a single uint32_t word. That's enough bits for pair-wise
174 // aliasing matrix of 8 heap locations.
175 static constexpr uint32_t kInitialAliasingMatrixBitVectorSize = 32;
176
Vladimir Markoef898422020-06-08 10:26:06 +0100177 explicit HeapLocationCollector(HGraph* graph, ScopedArenaAllocator* allocator)
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100178 : HGraphVisitor(graph),
Vladimir Markoef898422020-06-08 10:26:06 +0100179 allocator_(allocator),
180 ref_info_array_(allocator->Adapter(kArenaAllocLSA)),
181 heap_locations_(allocator->Adapter(kArenaAllocLSA)),
182 aliasing_matrix_(allocator,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100183 kInitialAliasingMatrixBitVectorSize,
184 true,
Vladimir Marko009d1662017-10-10 13:21:15 +0100185 kArenaAllocLSA),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100186 has_heap_stores_(false),
187 has_volatile_(false),
Vladimir Markoef898422020-06-08 10:26:06 +0100188 has_monitor_operations_(false) {
189 aliasing_matrix_.ClearAllBits();
190 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100191
192 void CleanUp() {
193 heap_locations_.clear();
194 ref_info_array_.clear();
195 }
196
197 size_t GetNumberOfHeapLocations() const {
198 return heap_locations_.size();
199 }
200
201 HeapLocation* GetHeapLocation(size_t index) const {
202 return heap_locations_[index];
203 }
204
205 HInstruction* HuntForOriginalReference(HInstruction* ref) const {
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000206 // An original reference can be transformed by instructions like:
207 // i0 NewArray
208 // i1 HInstruction(i0) <-- NullCheck, BoundType, IntermediateAddress.
209 // i2 ArrayGet(i1, index)
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100210 DCHECK(ref != nullptr);
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000211 while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100212 ref = ref->InputAt(0);
213 }
214 return ref;
215 }
216
217 ReferenceInfo* FindReferenceInfoOf(HInstruction* ref) const {
218 for (size_t i = 0; i < ref_info_array_.size(); i++) {
219 ReferenceInfo* ref_info = ref_info_array_[i];
220 if (ref_info->GetReference() == ref) {
221 DCHECK_EQ(i, ref_info->GetPosition());
222 return ref_info;
223 }
224 }
225 return nullptr;
226 }
227
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100228 size_t GetFieldHeapLocation(HInstruction* object, const FieldInfo* field) const {
229 DCHECK(object != nullptr);
230 DCHECK(field != nullptr);
231 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(object)),
Aart Bikb765a3f2018-05-10 14:47:48 -0700232 field->GetFieldType(),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100233 field->GetFieldOffset().SizeValue(),
234 nullptr,
235 HeapLocation::kScalar,
236 field->GetDeclaringClassDefIndex());
237 }
238
Aart Bikb765a3f2018-05-10 14:47:48 -0700239 size_t GetArrayHeapLocation(HInstruction* instruction) const {
240 DCHECK(instruction != nullptr);
241 HInstruction* array = instruction->InputAt(0);
242 HInstruction* index = instruction->InputAt(1);
243 DataType::Type type = instruction->GetType();
244 size_t vector_length = HeapLocation::kScalar;
245 if (instruction->IsArraySet()) {
246 type = instruction->AsArraySet()->GetComponentType();
247 } else if (instruction->IsVecStore() ||
248 instruction->IsVecLoad()) {
249 HVecOperation* vec_op = instruction->AsVecOperation();
250 type = vec_op->GetPackedType();
251 vector_length = vec_op->GetVectorLength();
252 } else {
253 DCHECK(instruction->IsArrayGet());
254 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100255 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
Aart Bikb765a3f2018-05-10 14:47:48 -0700256 type,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100257 HeapLocation::kInvalidFieldOffset,
258 index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100259 vector_length,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100260 HeapLocation::kDeclaringClassDefIndexForArrays);
261 }
262
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100263 bool HasHeapStores() const {
264 return has_heap_stores_;
265 }
266
267 bool HasVolatile() const {
268 return has_volatile_;
269 }
270
271 bool HasMonitorOps() const {
272 return has_monitor_operations_;
273 }
274
275 // Find and return the heap location index in heap_locations_.
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100276 // NOTE: When heap locations are created, potentially aliasing/overlapping
277 // accesses are given different indexes. This find function also
278 // doesn't take aliasing/overlapping into account. For example,
279 // this function returns three different indexes for:
280 // - ref_info=array, index=i, vector_length=kScalar;
281 // - ref_info=array, index=i, vector_length=2;
282 // - ref_info=array, index=i, vector_length=4;
283 // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
284 // these indexes alias.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100285 size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
Aart Bikb765a3f2018-05-10 14:47:48 -0700286 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100287 size_t offset,
288 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100289 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100290 int16_t declaring_class_def_index) const {
Aart Bikb765a3f2018-05-10 14:47:48 -0700291 DataType::Type lookup_type = DataType::ToSigned(type);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100292 for (size_t i = 0; i < heap_locations_.size(); i++) {
293 HeapLocation* loc = heap_locations_[i];
294 if (loc->GetReferenceInfo() == ref_info &&
Aart Bikb765a3f2018-05-10 14:47:48 -0700295 loc->GetType() == lookup_type &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100296 loc->GetOffset() == offset &&
297 loc->GetIndex() == index &&
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100298 loc->GetVectorLength() == vector_length &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100299 loc->GetDeclaringClassDefIndex() == declaring_class_def_index) {
300 return i;
301 }
302 }
303 return kHeapLocationNotFound;
304 }
305
306 // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
307 bool MayAlias(size_t index1, size_t index2) const {
308 if (index1 < index2) {
309 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index1, index2));
310 } else if (index1 > index2) {
311 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index2, index1));
312 } else {
313 DCHECK(false) << "index1 and index2 are expected to be different";
314 return true;
315 }
316 }
317
318 void BuildAliasingMatrix() {
319 const size_t number_of_locations = heap_locations_.size();
320 if (number_of_locations == 0) {
321 return;
322 }
323 size_t pos = 0;
324 // Compute aliasing info between every pair of different heap locations.
325 // Save the result in a matrix represented as a BitVector.
326 for (size_t i = 0; i < number_of_locations - 1; i++) {
327 for (size_t j = i + 1; j < number_of_locations; j++) {
328 if (ComputeMayAlias(i, j)) {
329 aliasing_matrix_.SetBit(CheckedAliasingMatrixPosition(i, j, pos));
330 }
331 pos++;
332 }
333 }
334 }
335
336 private:
337 // An allocation cannot alias with a name which already exists at the point
338 // of the allocation, such as a parameter or a load happening before the allocation.
339 bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
340 if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
341 // Any reference that can alias with the allocation must appear after it in the block/in
342 // the block's successors. In reverse post order, those instructions will be visited after
343 // the allocation.
344 return ref_info2->GetPosition() >= ref_info1->GetPosition();
345 }
346 return true;
347 }
348
349 bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
350 if (ref_info1 == ref_info2) {
351 return true;
352 } else if (ref_info1->IsSingleton()) {
353 return false;
354 } else if (ref_info2->IsSingleton()) {
355 return false;
356 } else if (!MayAliasWithPreexistenceChecking(ref_info1, ref_info2) ||
357 !MayAliasWithPreexistenceChecking(ref_info2, ref_info1)) {
358 return false;
359 }
360 return true;
361 }
362
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100363 bool CanArrayElementsAlias(const HInstruction* idx1,
364 const size_t vector_length1,
365 const HInstruction* idx2,
366 const size_t vector_length2) const;
xueliang.zhong016c0f12017-05-12 18:16:31 +0100367
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100368 // `index1` and `index2` are indices in the array of collected heap locations.
369 // Returns the position in the bit vector that tracks whether the two heap
370 // locations may alias.
371 size_t AliasingMatrixPosition(size_t index1, size_t index2) const {
372 DCHECK(index2 > index1);
373 const size_t number_of_locations = heap_locations_.size();
374 // It's (num_of_locations - 1) + ... + (num_of_locations - index1) + (index2 - index1 - 1).
375 return (number_of_locations * index1 - (1 + index1) * index1 / 2 + (index2 - index1 - 1));
376 }
377
378 // An additional position is passed in to make sure the calculated position is correct.
379 size_t CheckedAliasingMatrixPosition(size_t index1, size_t index2, size_t position) {
380 size_t calculated_position = AliasingMatrixPosition(index1, index2);
381 DCHECK_EQ(calculated_position, position);
382 return calculated_position;
383 }
384
385 // Compute if two locations may alias to each other.
386 bool ComputeMayAlias(size_t index1, size_t index2) const {
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700387 DCHECK_NE(index1, index2);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100388 HeapLocation* loc1 = heap_locations_[index1];
389 HeapLocation* loc2 = heap_locations_[index2];
390 if (loc1->GetOffset() != loc2->GetOffset()) {
391 // Either two different instance fields, or one is an instance
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100392 // field and the other is an array data.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100393 return false;
394 }
395 if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
396 // Different types.
397 return false;
398 }
399 if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
400 return false;
401 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100402 if (loc1->IsArray() && loc2->IsArray()) {
403 HInstruction* idx1 = loc1->GetIndex();
404 HInstruction* idx2 = loc2->GetIndex();
405 size_t vector_length1 = loc1->GetVectorLength();
406 size_t vector_length2 = loc2->GetVectorLength();
407 if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100408 return false;
409 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100410 }
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700411 loc1->SetHasAliasedLocations(true);
412 loc2->SetHasAliasedLocations(true);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100413 return true;
414 }
415
416 ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
417 ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
418 if (ref_info == nullptr) {
419 size_t pos = ref_info_array_.size();
Vladimir Markoef898422020-06-08 10:26:06 +0100420 ref_info = new (allocator_) ReferenceInfo(instruction, pos);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100421 ref_info_array_.push_back(ref_info);
422 }
423 return ref_info;
424 }
425
426 void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100427 if (instruction->GetType() != DataType::Type::kReference) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100428 return;
429 }
430 DCHECK(FindReferenceInfoOf(instruction) == nullptr);
431 GetOrCreateReferenceInfo(instruction);
432 }
433
Vladimir Marko3224f382020-06-23 14:19:53 +0100434 void MaybeCreateHeapLocation(HInstruction* ref,
435 DataType::Type type,
436 size_t offset,
437 HInstruction* index,
438 size_t vector_length,
439 int16_t declaring_class_def_index) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100440 HInstruction* original_ref = HuntForOriginalReference(ref);
441 ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
442 size_t heap_location_idx = FindHeapLocationIndex(
Aart Bikb765a3f2018-05-10 14:47:48 -0700443 ref_info, type, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100444 if (heap_location_idx == kHeapLocationNotFound) {
Vladimir Markoef898422020-06-08 10:26:06 +0100445 HeapLocation* heap_loc = new (allocator_)
Aart Bikb765a3f2018-05-10 14:47:48 -0700446 HeapLocation(ref_info, type, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100447 heap_locations_.push_back(heap_loc);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100448 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100449 }
450
Vladimir Marko3224f382020-06-23 14:19:53 +0100451 void VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100452 if (field_info.IsVolatile()) {
453 has_volatile_ = true;
454 }
Aart Bikb765a3f2018-05-10 14:47:48 -0700455 DataType::Type type = field_info.GetFieldType();
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100456 const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
457 const size_t offset = field_info.GetFieldOffset().SizeValue();
Vladimir Marko3224f382020-06-23 14:19:53 +0100458 MaybeCreateHeapLocation(ref,
459 type,
460 offset,
461 nullptr,
462 HeapLocation::kScalar,
463 declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100464 }
465
Aart Bikb765a3f2018-05-10 14:47:48 -0700466 void VisitArrayAccess(HInstruction* array,
467 HInstruction* index,
468 DataType::Type type,
469 size_t vector_length) {
Vladimir Marko3224f382020-06-23 14:19:53 +0100470 MaybeCreateHeapLocation(array,
Aart Bikb765a3f2018-05-10 14:47:48 -0700471 type,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100472 HeapLocation::kInvalidFieldOffset,
473 index,
474 vector_length,
475 HeapLocation::kDeclaringClassDefIndexForArrays);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100476 }
477
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100478 void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100479 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
480 CreateReferenceInfoForReferenceType(instruction);
481 }
482
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100483 void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
Vladimir Marko3224f382020-06-23 14:19:53 +0100484 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100485 has_heap_stores_ = true;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100486 }
487
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100488 void VisitStaticFieldGet(HStaticFieldGet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100489 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
490 CreateReferenceInfoForReferenceType(instruction);
491 }
492
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100493 void VisitStaticFieldSet(HStaticFieldSet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100494 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
495 has_heap_stores_ = true;
496 }
497
498 // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
499 // since we cannot accurately track the fields.
500
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100501 void VisitArrayGet(HArrayGet* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100502 HInstruction* array = instruction->InputAt(0);
503 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700504 DataType::Type type = instruction->GetType();
505 VisitArrayAccess(array, index, type, HeapLocation::kScalar);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100506 CreateReferenceInfoForReferenceType(instruction);
507 }
508
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100509 void VisitArraySet(HArraySet* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100510 HInstruction* array = instruction->InputAt(0);
511 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700512 DataType::Type type = instruction->GetComponentType();
513 VisitArrayAccess(array, index, type, HeapLocation::kScalar);
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100514 has_heap_stores_ = true;
515 }
516
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100517 void VisitVecLoad(HVecLoad* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100518 HInstruction* array = instruction->InputAt(0);
519 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700520 DataType::Type type = instruction->GetPackedType();
521 VisitArrayAccess(array, index, type, instruction->GetVectorLength());
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100522 CreateReferenceInfoForReferenceType(instruction);
523 }
524
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100525 void VisitVecStore(HVecStore* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100526 HInstruction* array = instruction->InputAt(0);
527 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700528 DataType::Type type = instruction->GetPackedType();
529 VisitArrayAccess(array, index, type, instruction->GetVectorLength());
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100530 has_heap_stores_ = true;
531 }
532
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100533 void VisitInstruction(HInstruction* instruction) override {
Mingyao Yangfef28842017-08-28 15:20:57 -0700534 // Any new-instance or new-array cannot alias with references that
535 // pre-exist the new-instance/new-array. We append entries into
536 // ref_info_array_ which keeps track of the order of creation
537 // of reference values since we visit the blocks in reverse post order.
538 //
539 // By default, VisitXXX() (including VisitPhi()) calls VisitInstruction(),
540 // unless VisitXXX() is overridden. VisitInstanceFieldGet() etc. above
541 // also call CreateReferenceInfoForReferenceType() explicitly.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100542 CreateReferenceInfoForReferenceType(instruction);
543 }
544
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100545 void VisitMonitorOperation(HMonitorOperation* monitor ATTRIBUTE_UNUSED) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100546 has_monitor_operations_ = true;
547 }
548
Vladimir Markoef898422020-06-08 10:26:06 +0100549 ScopedArenaAllocator* allocator_;
550 ScopedArenaVector<ReferenceInfo*> ref_info_array_; // All references used for heap accesses.
551 ScopedArenaVector<HeapLocation*> heap_locations_; // All heap locations.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100552 ArenaBitVector aliasing_matrix_; // aliasing info between each pair of locations.
553 bool has_heap_stores_; // If there is no heap stores, LSE acts as GVN with better
554 // alias analysis and won't be as effective.
555 bool has_volatile_; // If there are volatile field accesses.
556 bool has_monitor_operations_; // If there are monitor operations.
557
558 DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
559};
560
Vladimir Markoef898422020-06-08 10:26:06 +0100561class LoadStoreAnalysis {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100562 public:
Vladimir Markoef898422020-06-08 10:26:06 +0100563 explicit LoadStoreAnalysis(HGraph* graph, ScopedArenaAllocator* local_allocator)
564 : graph_(graph),
565 heap_location_collector_(graph, local_allocator) {}
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100566
567 const HeapLocationCollector& GetHeapLocationCollector() const {
568 return heap_location_collector_;
569 }
570
Vladimir Markoef898422020-06-08 10:26:06 +0100571 bool Run();
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100572
573 private:
Vladimir Markoef898422020-06-08 10:26:06 +0100574 HGraph* graph_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100575 HeapLocationCollector heap_location_collector_;
576
577 DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
578};
579
580} // namespace art
581
582#endif // ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_