blob: 999026cb6aeac9184993fa5ab42e7fc9bfc47199 [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
20#include "escape.h"
21#include "nodes.h"
22#include "optimization.h"
23
24namespace art {
25
26// A ReferenceInfo contains additional info about a reference such as
27// whether it's a singleton, returned, etc.
Vladimir Marko009d1662017-10-10 13:21:15 +010028class ReferenceInfo : public ArenaObject<kArenaAllocLSA> {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010029 public:
30 ReferenceInfo(HInstruction* reference, size_t pos)
31 : reference_(reference),
32 position_(pos),
33 is_singleton_(true),
34 is_singleton_and_not_returned_(true),
35 is_singleton_and_not_deopt_visible_(true),
36 has_index_aliasing_(false) {
37 CalculateEscape(reference_,
38 nullptr,
39 &is_singleton_,
40 &is_singleton_and_not_returned_,
41 &is_singleton_and_not_deopt_visible_);
42 }
43
44 HInstruction* GetReference() const {
45 return reference_;
46 }
47
48 size_t GetPosition() const {
49 return position_;
50 }
51
52 // Returns true if reference_ is the only name that can refer to its value during
53 // the lifetime of the method. So it's guaranteed to not have any alias in
54 // the method (including its callees).
55 bool IsSingleton() const {
56 return is_singleton_;
57 }
58
59 // Returns true if reference_ is a singleton and not returned to the caller or
60 // used as an environment local of an HDeoptimize instruction.
61 // The allocation and stores into reference_ may be eliminated for such cases.
62 bool IsSingletonAndRemovable() const {
63 return is_singleton_and_not_returned_ && is_singleton_and_not_deopt_visible_;
64 }
65
66 // Returns true if reference_ is a singleton and returned to the caller or
67 // used as an environment local of an HDeoptimize instruction.
68 bool IsSingletonAndNonRemovable() const {
69 return is_singleton_ &&
70 (!is_singleton_and_not_returned_ || !is_singleton_and_not_deopt_visible_);
71 }
72
73 bool HasIndexAliasing() {
74 return has_index_aliasing_;
75 }
76
77 void SetHasIndexAliasing(bool has_index_aliasing) {
78 // Only allow setting to true.
79 DCHECK(has_index_aliasing);
80 has_index_aliasing_ = has_index_aliasing;
81 }
82
83 private:
84 HInstruction* const reference_;
85 const size_t position_; // position in HeapLocationCollector's ref_info_array_.
86
87 // Can only be referred to by a single name in the method.
88 bool is_singleton_;
89 // Is singleton and not returned to caller.
90 bool is_singleton_and_not_returned_;
91 // Is singleton and not used as an environment local of HDeoptimize.
92 bool is_singleton_and_not_deopt_visible_;
93 // Some heap locations with reference_ have array index aliasing,
94 // e.g. arr[i] and arr[j] may be the same location.
95 bool has_index_aliasing_;
96
97 DISALLOW_COPY_AND_ASSIGN(ReferenceInfo);
98};
99
100// A heap location is a reference-offset/index pair that a value can be loaded from
101// or stored to.
Vladimir Marko009d1662017-10-10 13:21:15 +0100102class HeapLocation : public ArenaObject<kArenaAllocLSA> {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100103 public:
104 static constexpr size_t kInvalidFieldOffset = -1;
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100105 // Default value for heap locations which are not vector data.
106 static constexpr size_t kScalar = 1;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100107 // TODO: more fine-grained array types.
108 static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
109
110 HeapLocation(ReferenceInfo* ref_info,
111 size_t offset,
112 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100113 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100114 int16_t declaring_class_def_index)
115 : ref_info_(ref_info),
116 offset_(offset),
117 index_(index),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100118 vector_length_(vector_length),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100119 declaring_class_def_index_(declaring_class_def_index),
120 value_killed_by_loop_side_effects_(true) {
121 DCHECK(ref_info != nullptr);
122 DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
123 (offset != kInvalidFieldOffset && index == nullptr));
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100124 if (ref_info->IsSingleton() && !IsArray()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100125 // Assume this location's value cannot be killed by loop side effects
126 // until proven otherwise.
127 value_killed_by_loop_side_effects_ = false;
128 }
129 }
130
131 ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
132 size_t GetOffset() const { return offset_; }
133 HInstruction* GetIndex() const { return index_; }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100134 size_t GetVectorLength() const { return vector_length_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100135
136 // Returns the definition of declaring class' dex index.
137 // It's kDeclaringClassDefIndexForArrays for an array element.
138 int16_t GetDeclaringClassDefIndex() const {
139 return declaring_class_def_index_;
140 }
141
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100142 bool IsArray() const {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100143 return index_ != nullptr;
144 }
145
146 bool IsValueKilledByLoopSideEffects() const {
147 return value_killed_by_loop_side_effects_;
148 }
149
150 void SetValueKilledByLoopSideEffects(bool val) {
151 value_killed_by_loop_side_effects_ = val;
152 }
153
154 private:
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100155 // Reference for instance/static field, array element or vector data.
156 ReferenceInfo* const ref_info_;
157 // Offset of static/instance field.
158 // Invalid when this HeapLocation is not field.
159 const size_t offset_;
160 // Index of an array element or starting index of vector data.
161 // Invalid when this HeapLocation is not array.
162 HInstruction* const index_;
163 // Vector length of vector data.
164 // When this HeapLocation is not vector data, it's value is kScalar.
165 const size_t vector_length_;
166 // Declaring class's def's dex index.
167 // Invalid when this HeapLocation is not field access.
168 const int16_t declaring_class_def_index_;
169
170 // Value of this location may be killed by loop side effects
171 // because this location is stored into inside a loop.
172 // This gives better info on whether a singleton's location
173 // value may be killed by loop side effects.
174 bool value_killed_by_loop_side_effects_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100175
176 DISALLOW_COPY_AND_ASSIGN(HeapLocation);
177};
178
179// A HeapLocationCollector collects all relevant heap locations and keeps
180// an aliasing matrix for all locations.
181class HeapLocationCollector : public HGraphVisitor {
182 public:
183 static constexpr size_t kHeapLocationNotFound = -1;
184 // Start with a single uint32_t word. That's enough bits for pair-wise
185 // aliasing matrix of 8 heap locations.
186 static constexpr uint32_t kInitialAliasingMatrixBitVectorSize = 32;
187
188 explicit HeapLocationCollector(HGraph* graph)
189 : HGraphVisitor(graph),
Vladimir Marko009d1662017-10-10 13:21:15 +0100190 ref_info_array_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
191 heap_locations_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
Vladimir Markoca6fff82017-10-03 14:49:14 +0100192 aliasing_matrix_(graph->GetAllocator(),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100193 kInitialAliasingMatrixBitVectorSize,
194 true,
Vladimir Marko009d1662017-10-10 13:21:15 +0100195 kArenaAllocLSA),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100196 has_heap_stores_(false),
197 has_volatile_(false),
198 has_monitor_operations_(false) {}
199
200 void CleanUp() {
201 heap_locations_.clear();
202 ref_info_array_.clear();
203 }
204
205 size_t GetNumberOfHeapLocations() const {
206 return heap_locations_.size();
207 }
208
209 HeapLocation* GetHeapLocation(size_t index) const {
210 return heap_locations_[index];
211 }
212
213 HInstruction* HuntForOriginalReference(HInstruction* ref) const {
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000214 // An original reference can be transformed by instructions like:
215 // i0 NewArray
216 // i1 HInstruction(i0) <-- NullCheck, BoundType, IntermediateAddress.
217 // i2 ArrayGet(i1, index)
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100218 DCHECK(ref != nullptr);
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000219 while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100220 ref = ref->InputAt(0);
221 }
222 return ref;
223 }
224
225 ReferenceInfo* FindReferenceInfoOf(HInstruction* ref) const {
226 for (size_t i = 0; i < ref_info_array_.size(); i++) {
227 ReferenceInfo* ref_info = ref_info_array_[i];
228 if (ref_info->GetReference() == ref) {
229 DCHECK_EQ(i, ref_info->GetPosition());
230 return ref_info;
231 }
232 }
233 return nullptr;
234 }
235
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100236 size_t GetFieldHeapLocation(HInstruction* object, const FieldInfo* field) const {
237 DCHECK(object != nullptr);
238 DCHECK(field != nullptr);
239 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(object)),
240 field->GetFieldOffset().SizeValue(),
241 nullptr,
242 HeapLocation::kScalar,
243 field->GetDeclaringClassDefIndex());
244 }
245
246 size_t GetArrayHeapLocation(HInstruction* array,
247 HInstruction* index,
248 size_t vector_length = HeapLocation::kScalar) const {
xueliang.zhong016c0f12017-05-12 18:16:31 +0100249 DCHECK(array != nullptr);
250 DCHECK(index != nullptr);
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100251 DCHECK_GE(vector_length, HeapLocation::kScalar);
252 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
xueliang.zhong016c0f12017-05-12 18:16:31 +0100253 HeapLocation::kInvalidFieldOffset,
254 index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100255 vector_length,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100256 HeapLocation::kDeclaringClassDefIndexForArrays);
257 }
258
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100259 bool HasHeapStores() const {
260 return has_heap_stores_;
261 }
262
263 bool HasVolatile() const {
264 return has_volatile_;
265 }
266
267 bool HasMonitorOps() const {
268 return has_monitor_operations_;
269 }
270
271 // Find and return the heap location index in heap_locations_.
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100272 // NOTE: When heap locations are created, potentially aliasing/overlapping
273 // accesses are given different indexes. This find function also
274 // doesn't take aliasing/overlapping into account. For example,
275 // this function returns three different indexes for:
276 // - ref_info=array, index=i, vector_length=kScalar;
277 // - ref_info=array, index=i, vector_length=2;
278 // - ref_info=array, index=i, vector_length=4;
279 // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
280 // these indexes alias.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100281 size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
282 size_t offset,
283 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100284 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100285 int16_t declaring_class_def_index) const {
286 for (size_t i = 0; i < heap_locations_.size(); i++) {
287 HeapLocation* loc = heap_locations_[i];
288 if (loc->GetReferenceInfo() == ref_info &&
289 loc->GetOffset() == offset &&
290 loc->GetIndex() == index &&
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100291 loc->GetVectorLength() == vector_length &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100292 loc->GetDeclaringClassDefIndex() == declaring_class_def_index) {
293 return i;
294 }
295 }
296 return kHeapLocationNotFound;
297 }
298
299 // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
300 bool MayAlias(size_t index1, size_t index2) const {
301 if (index1 < index2) {
302 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index1, index2));
303 } else if (index1 > index2) {
304 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index2, index1));
305 } else {
306 DCHECK(false) << "index1 and index2 are expected to be different";
307 return true;
308 }
309 }
310
311 void BuildAliasingMatrix() {
312 const size_t number_of_locations = heap_locations_.size();
313 if (number_of_locations == 0) {
314 return;
315 }
316 size_t pos = 0;
317 // Compute aliasing info between every pair of different heap locations.
318 // Save the result in a matrix represented as a BitVector.
319 for (size_t i = 0; i < number_of_locations - 1; i++) {
320 for (size_t j = i + 1; j < number_of_locations; j++) {
321 if (ComputeMayAlias(i, j)) {
322 aliasing_matrix_.SetBit(CheckedAliasingMatrixPosition(i, j, pos));
323 }
324 pos++;
325 }
326 }
327 }
328
329 private:
330 // An allocation cannot alias with a name which already exists at the point
331 // of the allocation, such as a parameter or a load happening before the allocation.
332 bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
333 if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
334 // Any reference that can alias with the allocation must appear after it in the block/in
335 // the block's successors. In reverse post order, those instructions will be visited after
336 // the allocation.
337 return ref_info2->GetPosition() >= ref_info1->GetPosition();
338 }
339 return true;
340 }
341
342 bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
343 if (ref_info1 == ref_info2) {
344 return true;
345 } else if (ref_info1->IsSingleton()) {
346 return false;
347 } else if (ref_info2->IsSingleton()) {
348 return false;
349 } else if (!MayAliasWithPreexistenceChecking(ref_info1, ref_info2) ||
350 !MayAliasWithPreexistenceChecking(ref_info2, ref_info1)) {
351 return false;
352 }
353 return true;
354 }
355
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100356 bool CanArrayElementsAlias(const HInstruction* idx1,
357 const size_t vector_length1,
358 const HInstruction* idx2,
359 const size_t vector_length2) const;
xueliang.zhong016c0f12017-05-12 18:16:31 +0100360
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100361 // `index1` and `index2` are indices in the array of collected heap locations.
362 // Returns the position in the bit vector that tracks whether the two heap
363 // locations may alias.
364 size_t AliasingMatrixPosition(size_t index1, size_t index2) const {
365 DCHECK(index2 > index1);
366 const size_t number_of_locations = heap_locations_.size();
367 // It's (num_of_locations - 1) + ... + (num_of_locations - index1) + (index2 - index1 - 1).
368 return (number_of_locations * index1 - (1 + index1) * index1 / 2 + (index2 - index1 - 1));
369 }
370
371 // An additional position is passed in to make sure the calculated position is correct.
372 size_t CheckedAliasingMatrixPosition(size_t index1, size_t index2, size_t position) {
373 size_t calculated_position = AliasingMatrixPosition(index1, index2);
374 DCHECK_EQ(calculated_position, position);
375 return calculated_position;
376 }
377
378 // Compute if two locations may alias to each other.
379 bool ComputeMayAlias(size_t index1, size_t index2) const {
380 HeapLocation* loc1 = heap_locations_[index1];
381 HeapLocation* loc2 = heap_locations_[index2];
382 if (loc1->GetOffset() != loc2->GetOffset()) {
383 // Either two different instance fields, or one is an instance
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100384 // field and the other is an array data.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100385 return false;
386 }
387 if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
388 // Different types.
389 return false;
390 }
391 if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
392 return false;
393 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100394 if (loc1->IsArray() && loc2->IsArray()) {
395 HInstruction* idx1 = loc1->GetIndex();
396 HInstruction* idx2 = loc2->GetIndex();
397 size_t vector_length1 = loc1->GetVectorLength();
398 size_t vector_length2 = loc2->GetVectorLength();
399 if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100400 return false;
401 }
402 ReferenceInfo* ref_info = loc1->GetReferenceInfo();
403 ref_info->SetHasIndexAliasing(true);
404 }
405 return true;
406 }
407
408 ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
409 ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
410 if (ref_info == nullptr) {
411 size_t pos = ref_info_array_.size();
Vladimir Markoca6fff82017-10-03 14:49:14 +0100412 ref_info = new (GetGraph()->GetAllocator()) ReferenceInfo(instruction, pos);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100413 ref_info_array_.push_back(ref_info);
414 }
415 return ref_info;
416 }
417
418 void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100419 if (instruction->GetType() != DataType::Type::kReference) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100420 return;
421 }
422 DCHECK(FindReferenceInfoOf(instruction) == nullptr);
423 GetOrCreateReferenceInfo(instruction);
424 }
425
426 HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
427 size_t offset,
428 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100429 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100430 int16_t declaring_class_def_index) {
431 HInstruction* original_ref = HuntForOriginalReference(ref);
432 ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
433 size_t heap_location_idx = FindHeapLocationIndex(
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100434 ref_info, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100435 if (heap_location_idx == kHeapLocationNotFound) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100436 HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100437 HeapLocation(ref_info, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100438 heap_locations_.push_back(heap_loc);
439 return heap_loc;
440 }
441 return heap_locations_[heap_location_idx];
442 }
443
444 HeapLocation* VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
445 if (field_info.IsVolatile()) {
446 has_volatile_ = true;
447 }
448 const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
449 const size_t offset = field_info.GetFieldOffset().SizeValue();
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100450 return GetOrCreateHeapLocation(ref,
451 offset,
452 nullptr,
453 HeapLocation::kScalar,
454 declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100455 }
456
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100457 void VisitArrayAccess(HInstruction* array, HInstruction* index, size_t vector_length) {
458 GetOrCreateHeapLocation(array,
459 HeapLocation::kInvalidFieldOffset,
460 index,
461 vector_length,
462 HeapLocation::kDeclaringClassDefIndexForArrays);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100463 }
464
465 void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
466 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
467 CreateReferenceInfoForReferenceType(instruction);
468 }
469
470 void VisitInstanceFieldSet(HInstanceFieldSet* instruction) OVERRIDE {
471 HeapLocation* location = VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
472 has_heap_stores_ = true;
473 if (location->GetReferenceInfo()->IsSingleton()) {
474 // A singleton's location value may be killed by loop side effects if it's
475 // defined before that loop, and it's stored into inside that loop.
476 HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
477 if (loop_info != nullptr) {
478 HInstruction* ref = location->GetReferenceInfo()->GetReference();
479 DCHECK(ref->IsNewInstance());
480 if (loop_info->IsDefinedOutOfTheLoop(ref)) {
481 // ref's location value may be killed by this loop's side effects.
482 location->SetValueKilledByLoopSideEffects(true);
483 } else {
484 // ref is defined inside this loop so this loop's side effects cannot
485 // kill its location value at the loop header since ref/its location doesn't
486 // exist yet at the loop header.
487 }
488 }
489 } else {
490 // For non-singletons, value_killed_by_loop_side_effects_ is inited to
491 // true.
492 DCHECK_EQ(location->IsValueKilledByLoopSideEffects(), true);
493 }
494 }
495
496 void VisitStaticFieldGet(HStaticFieldGet* instruction) OVERRIDE {
497 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
498 CreateReferenceInfoForReferenceType(instruction);
499 }
500
501 void VisitStaticFieldSet(HStaticFieldSet* instruction) OVERRIDE {
502 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
503 has_heap_stores_ = true;
504 }
505
506 // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
507 // since we cannot accurately track the fields.
508
509 void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100510 HInstruction* array = instruction->InputAt(0);
511 HInstruction* index = instruction->InputAt(1);
512 VisitArrayAccess(array, index, HeapLocation::kScalar);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100513 CreateReferenceInfoForReferenceType(instruction);
514 }
515
516 void VisitArraySet(HArraySet* instruction) OVERRIDE {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100517 HInstruction* array = instruction->InputAt(0);
518 HInstruction* index = instruction->InputAt(1);
519 VisitArrayAccess(array, index, HeapLocation::kScalar);
520 has_heap_stores_ = true;
521 }
522
523 void VisitVecLoad(HVecLoad* instruction) OVERRIDE {
524 HInstruction* array = instruction->InputAt(0);
525 HInstruction* index = instruction->InputAt(1);
526 VisitArrayAccess(array, index, instruction->GetVectorLength());
527 CreateReferenceInfoForReferenceType(instruction);
528 }
529
530 void VisitVecStore(HVecStore* instruction) OVERRIDE {
531 HInstruction* array = instruction->InputAt(0);
532 HInstruction* index = instruction->InputAt(1);
533 VisitArrayAccess(array, index, instruction->GetVectorLength());
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100534 has_heap_stores_ = true;
535 }
536
Mingyao Yangfef28842017-08-28 15:20:57 -0700537 void VisitInstruction(HInstruction* instruction) OVERRIDE {
538 // Any new-instance or new-array cannot alias with references that
539 // pre-exist the new-instance/new-array. We append entries into
540 // ref_info_array_ which keeps track of the order of creation
541 // of reference values since we visit the blocks in reverse post order.
542 //
543 // By default, VisitXXX() (including VisitPhi()) calls VisitInstruction(),
544 // unless VisitXXX() is overridden. VisitInstanceFieldGet() etc. above
545 // also call CreateReferenceInfoForReferenceType() explicitly.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100546 CreateReferenceInfoForReferenceType(instruction);
547 }
548
549 void VisitMonitorOperation(HMonitorOperation* monitor ATTRIBUTE_UNUSED) OVERRIDE {
550 has_monitor_operations_ = true;
551 }
552
553 ArenaVector<ReferenceInfo*> ref_info_array_; // All references used for heap accesses.
554 ArenaVector<HeapLocation*> heap_locations_; // All heap locations.
555 ArenaBitVector aliasing_matrix_; // aliasing info between each pair of locations.
556 bool has_heap_stores_; // If there is no heap stores, LSE acts as GVN with better
557 // alias analysis and won't be as effective.
558 bool has_volatile_; // If there are volatile field accesses.
559 bool has_monitor_operations_; // If there are monitor operations.
560
561 DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
562};
563
564class LoadStoreAnalysis : public HOptimization {
565 public:
566 explicit LoadStoreAnalysis(HGraph* graph)
567 : HOptimization(graph, kLoadStoreAnalysisPassName),
568 heap_location_collector_(graph) {}
569
570 const HeapLocationCollector& GetHeapLocationCollector() const {
571 return heap_location_collector_;
572 }
573
574 void Run() OVERRIDE;
575
576 static constexpr const char* kLoadStoreAnalysisPassName = "load_store_analysis";
577
578 private:
579 HeapLocationCollector heap_location_collector_;
580
581 DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
582};
583
584} // namespace art
585
586#endif // ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_