blob: f84846d1b0ff66f038170932df5f8cd8b149daa4 [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),
Mingyao Yang0e3151b2017-10-30 11:19:57 -070035 is_singleton_and_not_deopt_visible_(true) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010036 CalculateEscape(reference_,
37 nullptr,
38 &is_singleton_,
39 &is_singleton_and_not_returned_,
40 &is_singleton_and_not_deopt_visible_);
41 }
42
43 HInstruction* GetReference() const {
44 return reference_;
45 }
46
47 size_t GetPosition() const {
48 return position_;
49 }
50
51 // Returns true if reference_ is the only name that can refer to its value during
52 // the lifetime of the method. So it's guaranteed to not have any alias in
53 // the method (including its callees).
54 bool IsSingleton() const {
55 return is_singleton_;
56 }
57
58 // Returns true if reference_ is a singleton and not returned to the caller or
59 // used as an environment local of an HDeoptimize instruction.
60 // The allocation and stores into reference_ may be eliminated for such cases.
61 bool IsSingletonAndRemovable() const {
62 return is_singleton_and_not_returned_ && is_singleton_and_not_deopt_visible_;
63 }
64
65 // Returns true if reference_ is a singleton and returned to the caller or
66 // used as an environment local of an HDeoptimize instruction.
67 bool IsSingletonAndNonRemovable() const {
68 return is_singleton_ &&
69 (!is_singleton_and_not_returned_ || !is_singleton_and_not_deopt_visible_);
70 }
71
xueliang.zhongc239a2b2017-04-27 15:31:37 +010072 private:
73 HInstruction* const reference_;
74 const size_t position_; // position in HeapLocationCollector's ref_info_array_.
75
76 // Can only be referred to by a single name in the method.
77 bool is_singleton_;
78 // Is singleton and not returned to caller.
79 bool is_singleton_and_not_returned_;
80 // Is singleton and not used as an environment local of HDeoptimize.
81 bool is_singleton_and_not_deopt_visible_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +010082
83 DISALLOW_COPY_AND_ASSIGN(ReferenceInfo);
84};
85
86// A heap location is a reference-offset/index pair that a value can be loaded from
87// or stored to.
Vladimir Marko009d1662017-10-10 13:21:15 +010088class HeapLocation : public ArenaObject<kArenaAllocLSA> {
xueliang.zhongc239a2b2017-04-27 15:31:37 +010089 public:
90 static constexpr size_t kInvalidFieldOffset = -1;
xueliang.zhongb50b16a2017-09-19 17:43:29 +010091 // Default value for heap locations which are not vector data.
92 static constexpr size_t kScalar = 1;
xueliang.zhongc239a2b2017-04-27 15:31:37 +010093 // TODO: more fine-grained array types.
94 static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
95
96 HeapLocation(ReferenceInfo* ref_info,
97 size_t offset,
98 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +010099 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100100 int16_t declaring_class_def_index)
101 : ref_info_(ref_info),
102 offset_(offset),
103 index_(index),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100104 vector_length_(vector_length),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100105 declaring_class_def_index_(declaring_class_def_index),
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700106 value_killed_by_loop_side_effects_(true),
107 has_aliased_locations_(false) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100108 DCHECK(ref_info != nullptr);
109 DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
110 (offset != kInvalidFieldOffset && index == nullptr));
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100111 if (ref_info->IsSingleton() && !IsArray()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100112 // Assume this location's value cannot be killed by loop side effects
113 // until proven otherwise.
114 value_killed_by_loop_side_effects_ = false;
115 }
116 }
117
118 ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
119 size_t GetOffset() const { return offset_; }
120 HInstruction* GetIndex() const { return index_; }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100121 size_t GetVectorLength() const { return vector_length_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100122
123 // Returns the definition of declaring class' dex index.
124 // It's kDeclaringClassDefIndexForArrays for an array element.
125 int16_t GetDeclaringClassDefIndex() const {
126 return declaring_class_def_index_;
127 }
128
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100129 bool IsArray() const {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100130 return index_ != nullptr;
131 }
132
133 bool IsValueKilledByLoopSideEffects() const {
134 return value_killed_by_loop_side_effects_;
135 }
136
137 void SetValueKilledByLoopSideEffects(bool val) {
138 value_killed_by_loop_side_effects_ = val;
139 }
140
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700141 bool HasAliasedLocations() const {
142 return has_aliased_locations_;
143 }
144
145 void SetHasAliasedLocations(bool val) {
146 has_aliased_locations_ = val;
147 }
148
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100149 private:
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100150 // Reference for instance/static field, array element or vector data.
151 ReferenceInfo* const ref_info_;
152 // Offset of static/instance field.
153 // Invalid when this HeapLocation is not field.
154 const size_t offset_;
155 // Index of an array element or starting index of vector data.
156 // Invalid when this HeapLocation is not array.
157 HInstruction* const index_;
158 // Vector length of vector data.
159 // When this HeapLocation is not vector data, it's value is kScalar.
160 const size_t vector_length_;
161 // Declaring class's def's dex index.
162 // Invalid when this HeapLocation is not field access.
163 const int16_t declaring_class_def_index_;
164
165 // Value of this location may be killed by loop side effects
166 // because this location is stored into inside a loop.
167 // This gives better info on whether a singleton's location
168 // value may be killed by loop side effects.
169 bool value_killed_by_loop_side_effects_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100170
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700171 // Has aliased heap locations in the method, due to either the
172 // reference is aliased or the array element is aliased via different
173 // index names.
174 bool has_aliased_locations_;
175
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100176 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 {
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700380 DCHECK_NE(index1, index2);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100381 HeapLocation* loc1 = heap_locations_[index1];
382 HeapLocation* loc2 = heap_locations_[index2];
383 if (loc1->GetOffset() != loc2->GetOffset()) {
384 // Either two different instance fields, or one is an instance
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100385 // field and the other is an array data.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100386 return false;
387 }
388 if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
389 // Different types.
390 return false;
391 }
392 if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
393 return false;
394 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100395 if (loc1->IsArray() && loc2->IsArray()) {
396 HInstruction* idx1 = loc1->GetIndex();
397 HInstruction* idx2 = loc2->GetIndex();
398 size_t vector_length1 = loc1->GetVectorLength();
399 size_t vector_length2 = loc2->GetVectorLength();
400 if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100401 return false;
402 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100403 }
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700404 loc1->SetHasAliasedLocations(true);
405 loc2->SetHasAliasedLocations(true);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100406 return true;
407 }
408
409 ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
410 ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
411 if (ref_info == nullptr) {
412 size_t pos = ref_info_array_.size();
Vladimir Markoca6fff82017-10-03 14:49:14 +0100413 ref_info = new (GetGraph()->GetAllocator()) ReferenceInfo(instruction, pos);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100414 ref_info_array_.push_back(ref_info);
415 }
416 return ref_info;
417 }
418
419 void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100420 if (instruction->GetType() != DataType::Type::kReference) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100421 return;
422 }
423 DCHECK(FindReferenceInfoOf(instruction) == nullptr);
424 GetOrCreateReferenceInfo(instruction);
425 }
426
427 HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
428 size_t offset,
429 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100430 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100431 int16_t declaring_class_def_index) {
432 HInstruction* original_ref = HuntForOriginalReference(ref);
433 ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
434 size_t heap_location_idx = FindHeapLocationIndex(
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100435 ref_info, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100436 if (heap_location_idx == kHeapLocationNotFound) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100437 HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100438 HeapLocation(ref_info, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100439 heap_locations_.push_back(heap_loc);
440 return heap_loc;
441 }
442 return heap_locations_[heap_location_idx];
443 }
444
445 HeapLocation* VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
446 if (field_info.IsVolatile()) {
447 has_volatile_ = true;
448 }
449 const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
450 const size_t offset = field_info.GetFieldOffset().SizeValue();
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100451 return GetOrCreateHeapLocation(ref,
452 offset,
453 nullptr,
454 HeapLocation::kScalar,
455 declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100456 }
457
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100458 void VisitArrayAccess(HInstruction* array, HInstruction* index, size_t vector_length) {
459 GetOrCreateHeapLocation(array,
460 HeapLocation::kInvalidFieldOffset,
461 index,
462 vector_length,
463 HeapLocation::kDeclaringClassDefIndexForArrays);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100464 }
465
466 void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
467 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
468 CreateReferenceInfoForReferenceType(instruction);
469 }
470
471 void VisitInstanceFieldSet(HInstanceFieldSet* instruction) OVERRIDE {
472 HeapLocation* location = VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
473 has_heap_stores_ = true;
474 if (location->GetReferenceInfo()->IsSingleton()) {
475 // A singleton's location value may be killed by loop side effects if it's
476 // defined before that loop, and it's stored into inside that loop.
477 HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
478 if (loop_info != nullptr) {
479 HInstruction* ref = location->GetReferenceInfo()->GetReference();
480 DCHECK(ref->IsNewInstance());
481 if (loop_info->IsDefinedOutOfTheLoop(ref)) {
482 // ref's location value may be killed by this loop's side effects.
483 location->SetValueKilledByLoopSideEffects(true);
484 } else {
485 // ref is defined inside this loop so this loop's side effects cannot
486 // kill its location value at the loop header since ref/its location doesn't
487 // exist yet at the loop header.
488 }
489 }
490 } else {
491 // For non-singletons, value_killed_by_loop_side_effects_ is inited to
492 // true.
493 DCHECK_EQ(location->IsValueKilledByLoopSideEffects(), true);
494 }
495 }
496
497 void VisitStaticFieldGet(HStaticFieldGet* instruction) OVERRIDE {
498 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
499 CreateReferenceInfoForReferenceType(instruction);
500 }
501
502 void VisitStaticFieldSet(HStaticFieldSet* instruction) OVERRIDE {
503 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
504 has_heap_stores_ = true;
505 }
506
507 // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
508 // since we cannot accurately track the fields.
509
510 void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100511 HInstruction* array = instruction->InputAt(0);
512 HInstruction* index = instruction->InputAt(1);
513 VisitArrayAccess(array, index, HeapLocation::kScalar);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100514 CreateReferenceInfoForReferenceType(instruction);
515 }
516
517 void VisitArraySet(HArraySet* instruction) OVERRIDE {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100518 HInstruction* array = instruction->InputAt(0);
519 HInstruction* index = instruction->InputAt(1);
520 VisitArrayAccess(array, index, HeapLocation::kScalar);
521 has_heap_stores_ = true;
522 }
523
524 void VisitVecLoad(HVecLoad* instruction) OVERRIDE {
525 HInstruction* array = instruction->InputAt(0);
526 HInstruction* index = instruction->InputAt(1);
527 VisitArrayAccess(array, index, instruction->GetVectorLength());
528 CreateReferenceInfoForReferenceType(instruction);
529 }
530
531 void VisitVecStore(HVecStore* instruction) OVERRIDE {
532 HInstruction* array = instruction->InputAt(0);
533 HInstruction* index = instruction->InputAt(1);
534 VisitArrayAccess(array, index, instruction->GetVectorLength());
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100535 has_heap_stores_ = true;
536 }
537
Mingyao Yangfef28842017-08-28 15:20:57 -0700538 void VisitInstruction(HInstruction* instruction) OVERRIDE {
539 // Any new-instance or new-array cannot alias with references that
540 // pre-exist the new-instance/new-array. We append entries into
541 // ref_info_array_ which keeps track of the order of creation
542 // of reference values since we visit the blocks in reverse post order.
543 //
544 // By default, VisitXXX() (including VisitPhi()) calls VisitInstruction(),
545 // unless VisitXXX() is overridden. VisitInstanceFieldGet() etc. above
546 // also call CreateReferenceInfoForReferenceType() explicitly.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100547 CreateReferenceInfoForReferenceType(instruction);
548 }
549
550 void VisitMonitorOperation(HMonitorOperation* monitor ATTRIBUTE_UNUSED) OVERRIDE {
551 has_monitor_operations_ = true;
552 }
553
554 ArenaVector<ReferenceInfo*> ref_info_array_; // All references used for heap accesses.
555 ArenaVector<HeapLocation*> heap_locations_; // All heap locations.
556 ArenaBitVector aliasing_matrix_; // aliasing info between each pair of locations.
557 bool has_heap_stores_; // If there is no heap stores, LSE acts as GVN with better
558 // alias analysis and won't be as effective.
559 bool has_volatile_; // If there are volatile field accesses.
560 bool has_monitor_operations_; // If there are monitor operations.
561
562 DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
563};
564
565class LoadStoreAnalysis : public HOptimization {
566 public:
Aart Bik2ca10eb2017-11-15 15:17:53 -0800567 explicit LoadStoreAnalysis(HGraph* graph, const char* name = kLoadStoreAnalysisPassName)
568 : HOptimization(graph, name),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100569 heap_location_collector_(graph) {}
570
571 const HeapLocationCollector& GetHeapLocationCollector() const {
572 return heap_location_collector_;
573 }
574
Aart Bik24773202018-04-26 10:28:51 -0700575 bool Run() OVERRIDE;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100576
577 static constexpr const char* kLoadStoreAnalysisPassName = "load_store_analysis";
578
579 private:
580 HeapLocationCollector heap_location_collector_;
581
582 DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
583};
584
585} // namespace art
586
587#endif // ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_