blob: 15e7045ec6fb4c1c9cb63d3f09d2db7784869097 [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 value_killed_by_loop_side_effects_(true),
111 has_aliased_locations_(false) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100112 DCHECK(ref_info != nullptr);
113 DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
114 (offset != kInvalidFieldOffset && index == nullptr));
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100115 if (ref_info->IsSingleton() && !IsArray()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100116 // Assume this location's value cannot be killed by loop side effects
117 // until proven otherwise.
118 value_killed_by_loop_side_effects_ = false;
119 }
120 }
121
122 ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
Aart Bikb765a3f2018-05-10 14:47:48 -0700123 DataType::Type GetType() const { return type_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100124 size_t GetOffset() const { return offset_; }
125 HInstruction* GetIndex() const { return index_; }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100126 size_t GetVectorLength() const { return vector_length_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100127
128 // Returns the definition of declaring class' dex index.
129 // It's kDeclaringClassDefIndexForArrays for an array element.
130 int16_t GetDeclaringClassDefIndex() const {
131 return declaring_class_def_index_;
132 }
133
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100134 bool IsArray() const {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100135 return index_ != nullptr;
136 }
137
138 bool IsValueKilledByLoopSideEffects() const {
139 return value_killed_by_loop_side_effects_;
140 }
141
142 void SetValueKilledByLoopSideEffects(bool val) {
143 value_killed_by_loop_side_effects_ = val;
144 }
145
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700146 bool HasAliasedLocations() const {
147 return has_aliased_locations_;
148 }
149
150 void SetHasAliasedLocations(bool val) {
151 has_aliased_locations_ = val;
152 }
153
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100154 private:
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100155 // Reference for instance/static field, array element or vector data.
156 ReferenceInfo* const ref_info_;
Aart Bikb765a3f2018-05-10 14:47:48 -0700157 // Type of data residing at HeapLocation (always signed for integral
158 // data since e.g. a[i] and a[i] & 0xff are represented by differently
159 // signed types; char vs short are disambiguated through the reference).
160 const DataType::Type type_;
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100161 // Offset of static/instance field.
162 // Invalid when this HeapLocation is not field.
163 const size_t offset_;
164 // Index of an array element or starting index of vector data.
165 // Invalid when this HeapLocation is not array.
166 HInstruction* const index_;
167 // Vector length of vector data.
168 // When this HeapLocation is not vector data, it's value is kScalar.
169 const size_t vector_length_;
170 // Declaring class's def's dex index.
171 // Invalid when this HeapLocation is not field access.
172 const int16_t declaring_class_def_index_;
173
174 // Value of this location may be killed by loop side effects
175 // because this location is stored into inside a loop.
176 // This gives better info on whether a singleton's location
177 // value may be killed by loop side effects.
178 bool value_killed_by_loop_side_effects_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100179
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700180 // Has aliased heap locations in the method, due to either the
181 // reference is aliased or the array element is aliased via different
182 // index names.
183 bool has_aliased_locations_;
184
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100185 DISALLOW_COPY_AND_ASSIGN(HeapLocation);
186};
187
188// A HeapLocationCollector collects all relevant heap locations and keeps
189// an aliasing matrix for all locations.
190class HeapLocationCollector : public HGraphVisitor {
191 public:
192 static constexpr size_t kHeapLocationNotFound = -1;
193 // Start with a single uint32_t word. That's enough bits for pair-wise
194 // aliasing matrix of 8 heap locations.
195 static constexpr uint32_t kInitialAliasingMatrixBitVectorSize = 32;
196
Vladimir Markoef898422020-06-08 10:26:06 +0100197 explicit HeapLocationCollector(HGraph* graph, ScopedArenaAllocator* allocator)
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100198 : HGraphVisitor(graph),
Vladimir Markoef898422020-06-08 10:26:06 +0100199 allocator_(allocator),
200 ref_info_array_(allocator->Adapter(kArenaAllocLSA)),
201 heap_locations_(allocator->Adapter(kArenaAllocLSA)),
202 aliasing_matrix_(allocator,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100203 kInitialAliasingMatrixBitVectorSize,
204 true,
Vladimir Marko009d1662017-10-10 13:21:15 +0100205 kArenaAllocLSA),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100206 has_heap_stores_(false),
207 has_volatile_(false),
Vladimir Markoef898422020-06-08 10:26:06 +0100208 has_monitor_operations_(false) {
209 aliasing_matrix_.ClearAllBits();
210 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100211
212 void CleanUp() {
213 heap_locations_.clear();
214 ref_info_array_.clear();
215 }
216
217 size_t GetNumberOfHeapLocations() const {
218 return heap_locations_.size();
219 }
220
221 HeapLocation* GetHeapLocation(size_t index) const {
222 return heap_locations_[index];
223 }
224
225 HInstruction* HuntForOriginalReference(HInstruction* ref) const {
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000226 // An original reference can be transformed by instructions like:
227 // i0 NewArray
228 // i1 HInstruction(i0) <-- NullCheck, BoundType, IntermediateAddress.
229 // i2 ArrayGet(i1, index)
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100230 DCHECK(ref != nullptr);
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000231 while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100232 ref = ref->InputAt(0);
233 }
234 return ref;
235 }
236
237 ReferenceInfo* FindReferenceInfoOf(HInstruction* ref) const {
238 for (size_t i = 0; i < ref_info_array_.size(); i++) {
239 ReferenceInfo* ref_info = ref_info_array_[i];
240 if (ref_info->GetReference() == ref) {
241 DCHECK_EQ(i, ref_info->GetPosition());
242 return ref_info;
243 }
244 }
245 return nullptr;
246 }
247
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100248 size_t GetFieldHeapLocation(HInstruction* object, const FieldInfo* field) const {
249 DCHECK(object != nullptr);
250 DCHECK(field != nullptr);
251 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(object)),
Aart Bikb765a3f2018-05-10 14:47:48 -0700252 field->GetFieldType(),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100253 field->GetFieldOffset().SizeValue(),
254 nullptr,
255 HeapLocation::kScalar,
256 field->GetDeclaringClassDefIndex());
257 }
258
Aart Bikb765a3f2018-05-10 14:47:48 -0700259 size_t GetArrayHeapLocation(HInstruction* instruction) const {
260 DCHECK(instruction != nullptr);
261 HInstruction* array = instruction->InputAt(0);
262 HInstruction* index = instruction->InputAt(1);
263 DataType::Type type = instruction->GetType();
264 size_t vector_length = HeapLocation::kScalar;
265 if (instruction->IsArraySet()) {
266 type = instruction->AsArraySet()->GetComponentType();
267 } else if (instruction->IsVecStore() ||
268 instruction->IsVecLoad()) {
269 HVecOperation* vec_op = instruction->AsVecOperation();
270 type = vec_op->GetPackedType();
271 vector_length = vec_op->GetVectorLength();
272 } else {
273 DCHECK(instruction->IsArrayGet());
274 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100275 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
Aart Bikb765a3f2018-05-10 14:47:48 -0700276 type,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100277 HeapLocation::kInvalidFieldOffset,
278 index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100279 vector_length,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100280 HeapLocation::kDeclaringClassDefIndexForArrays);
281 }
282
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100283 bool HasHeapStores() const {
284 return has_heap_stores_;
285 }
286
287 bool HasVolatile() const {
288 return has_volatile_;
289 }
290
291 bool HasMonitorOps() const {
292 return has_monitor_operations_;
293 }
294
295 // Find and return the heap location index in heap_locations_.
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100296 // NOTE: When heap locations are created, potentially aliasing/overlapping
297 // accesses are given different indexes. This find function also
298 // doesn't take aliasing/overlapping into account. For example,
299 // this function returns three different indexes for:
300 // - ref_info=array, index=i, vector_length=kScalar;
301 // - ref_info=array, index=i, vector_length=2;
302 // - ref_info=array, index=i, vector_length=4;
303 // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
304 // these indexes alias.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100305 size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
Aart Bikb765a3f2018-05-10 14:47:48 -0700306 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100307 size_t offset,
308 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100309 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100310 int16_t declaring_class_def_index) const {
Aart Bikb765a3f2018-05-10 14:47:48 -0700311 DataType::Type lookup_type = DataType::ToSigned(type);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100312 for (size_t i = 0; i < heap_locations_.size(); i++) {
313 HeapLocation* loc = heap_locations_[i];
314 if (loc->GetReferenceInfo() == ref_info &&
Aart Bikb765a3f2018-05-10 14:47:48 -0700315 loc->GetType() == lookup_type &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100316 loc->GetOffset() == offset &&
317 loc->GetIndex() == index &&
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100318 loc->GetVectorLength() == vector_length &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100319 loc->GetDeclaringClassDefIndex() == declaring_class_def_index) {
320 return i;
321 }
322 }
323 return kHeapLocationNotFound;
324 }
325
326 // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
327 bool MayAlias(size_t index1, size_t index2) const {
328 if (index1 < index2) {
329 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index1, index2));
330 } else if (index1 > index2) {
331 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index2, index1));
332 } else {
333 DCHECK(false) << "index1 and index2 are expected to be different";
334 return true;
335 }
336 }
337
338 void BuildAliasingMatrix() {
339 const size_t number_of_locations = heap_locations_.size();
340 if (number_of_locations == 0) {
341 return;
342 }
343 size_t pos = 0;
344 // Compute aliasing info between every pair of different heap locations.
345 // Save the result in a matrix represented as a BitVector.
346 for (size_t i = 0; i < number_of_locations - 1; i++) {
347 for (size_t j = i + 1; j < number_of_locations; j++) {
348 if (ComputeMayAlias(i, j)) {
349 aliasing_matrix_.SetBit(CheckedAliasingMatrixPosition(i, j, pos));
350 }
351 pos++;
352 }
353 }
354 }
355
356 private:
357 // An allocation cannot alias with a name which already exists at the point
358 // of the allocation, such as a parameter or a load happening before the allocation.
359 bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
360 if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
361 // Any reference that can alias with the allocation must appear after it in the block/in
362 // the block's successors. In reverse post order, those instructions will be visited after
363 // the allocation.
364 return ref_info2->GetPosition() >= ref_info1->GetPosition();
365 }
366 return true;
367 }
368
369 bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
370 if (ref_info1 == ref_info2) {
371 return true;
372 } else if (ref_info1->IsSingleton()) {
373 return false;
374 } else if (ref_info2->IsSingleton()) {
375 return false;
376 } else if (!MayAliasWithPreexistenceChecking(ref_info1, ref_info2) ||
377 !MayAliasWithPreexistenceChecking(ref_info2, ref_info1)) {
378 return false;
379 }
380 return true;
381 }
382
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100383 bool CanArrayElementsAlias(const HInstruction* idx1,
384 const size_t vector_length1,
385 const HInstruction* idx2,
386 const size_t vector_length2) const;
xueliang.zhong016c0f12017-05-12 18:16:31 +0100387
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100388 // `index1` and `index2` are indices in the array of collected heap locations.
389 // Returns the position in the bit vector that tracks whether the two heap
390 // locations may alias.
391 size_t AliasingMatrixPosition(size_t index1, size_t index2) const {
392 DCHECK(index2 > index1);
393 const size_t number_of_locations = heap_locations_.size();
394 // It's (num_of_locations - 1) + ... + (num_of_locations - index1) + (index2 - index1 - 1).
395 return (number_of_locations * index1 - (1 + index1) * index1 / 2 + (index2 - index1 - 1));
396 }
397
398 // An additional position is passed in to make sure the calculated position is correct.
399 size_t CheckedAliasingMatrixPosition(size_t index1, size_t index2, size_t position) {
400 size_t calculated_position = AliasingMatrixPosition(index1, index2);
401 DCHECK_EQ(calculated_position, position);
402 return calculated_position;
403 }
404
405 // Compute if two locations may alias to each other.
406 bool ComputeMayAlias(size_t index1, size_t index2) const {
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700407 DCHECK_NE(index1, index2);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100408 HeapLocation* loc1 = heap_locations_[index1];
409 HeapLocation* loc2 = heap_locations_[index2];
410 if (loc1->GetOffset() != loc2->GetOffset()) {
411 // Either two different instance fields, or one is an instance
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100412 // field and the other is an array data.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100413 return false;
414 }
415 if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
416 // Different types.
417 return false;
418 }
419 if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
420 return false;
421 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100422 if (loc1->IsArray() && loc2->IsArray()) {
423 HInstruction* idx1 = loc1->GetIndex();
424 HInstruction* idx2 = loc2->GetIndex();
425 size_t vector_length1 = loc1->GetVectorLength();
426 size_t vector_length2 = loc2->GetVectorLength();
427 if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100428 return false;
429 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100430 }
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700431 loc1->SetHasAliasedLocations(true);
432 loc2->SetHasAliasedLocations(true);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100433 return true;
434 }
435
436 ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
437 ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
438 if (ref_info == nullptr) {
439 size_t pos = ref_info_array_.size();
Vladimir Markoef898422020-06-08 10:26:06 +0100440 ref_info = new (allocator_) ReferenceInfo(instruction, pos);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100441 ref_info_array_.push_back(ref_info);
442 }
443 return ref_info;
444 }
445
446 void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100447 if (instruction->GetType() != DataType::Type::kReference) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100448 return;
449 }
450 DCHECK(FindReferenceInfoOf(instruction) == nullptr);
451 GetOrCreateReferenceInfo(instruction);
452 }
453
454 HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
Aart Bikb765a3f2018-05-10 14:47:48 -0700455 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100456 size_t offset,
457 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100458 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100459 int16_t declaring_class_def_index) {
460 HInstruction* original_ref = HuntForOriginalReference(ref);
461 ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
462 size_t heap_location_idx = FindHeapLocationIndex(
Aart Bikb765a3f2018-05-10 14:47:48 -0700463 ref_info, type, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100464 if (heap_location_idx == kHeapLocationNotFound) {
Vladimir Markoef898422020-06-08 10:26:06 +0100465 HeapLocation* heap_loc = new (allocator_)
Aart Bikb765a3f2018-05-10 14:47:48 -0700466 HeapLocation(ref_info, type, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100467 heap_locations_.push_back(heap_loc);
468 return heap_loc;
469 }
470 return heap_locations_[heap_location_idx];
471 }
472
473 HeapLocation* VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
474 if (field_info.IsVolatile()) {
475 has_volatile_ = true;
476 }
Aart Bikb765a3f2018-05-10 14:47:48 -0700477 DataType::Type type = field_info.GetFieldType();
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100478 const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
479 const size_t offset = field_info.GetFieldOffset().SizeValue();
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100480 return GetOrCreateHeapLocation(ref,
Aart Bikb765a3f2018-05-10 14:47:48 -0700481 type,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100482 offset,
483 nullptr,
484 HeapLocation::kScalar,
485 declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100486 }
487
Aart Bikb765a3f2018-05-10 14:47:48 -0700488 void VisitArrayAccess(HInstruction* array,
489 HInstruction* index,
490 DataType::Type type,
491 size_t vector_length) {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100492 GetOrCreateHeapLocation(array,
Aart Bikb765a3f2018-05-10 14:47:48 -0700493 type,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100494 HeapLocation::kInvalidFieldOffset,
495 index,
496 vector_length,
497 HeapLocation::kDeclaringClassDefIndexForArrays);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100498 }
499
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100500 void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100501 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
502 CreateReferenceInfoForReferenceType(instruction);
503 }
504
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100505 void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100506 HeapLocation* location = VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
507 has_heap_stores_ = true;
508 if (location->GetReferenceInfo()->IsSingleton()) {
509 // A singleton's location value may be killed by loop side effects if it's
510 // defined before that loop, and it's stored into inside that loop.
511 HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
512 if (loop_info != nullptr) {
513 HInstruction* ref = location->GetReferenceInfo()->GetReference();
514 DCHECK(ref->IsNewInstance());
515 if (loop_info->IsDefinedOutOfTheLoop(ref)) {
516 // ref's location value may be killed by this loop's side effects.
517 location->SetValueKilledByLoopSideEffects(true);
518 } else {
519 // ref is defined inside this loop so this loop's side effects cannot
520 // kill its location value at the loop header since ref/its location doesn't
521 // exist yet at the loop header.
522 }
523 }
524 } else {
525 // For non-singletons, value_killed_by_loop_side_effects_ is inited to
526 // true.
527 DCHECK_EQ(location->IsValueKilledByLoopSideEffects(), true);
528 }
529 }
530
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100531 void VisitStaticFieldGet(HStaticFieldGet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100532 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
533 CreateReferenceInfoForReferenceType(instruction);
534 }
535
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100536 void VisitStaticFieldSet(HStaticFieldSet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100537 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
538 has_heap_stores_ = true;
539 }
540
541 // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
542 // since we cannot accurately track the fields.
543
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100544 void VisitArrayGet(HArrayGet* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100545 HInstruction* array = instruction->InputAt(0);
546 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700547 DataType::Type type = instruction->GetType();
548 VisitArrayAccess(array, index, type, HeapLocation::kScalar);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100549 CreateReferenceInfoForReferenceType(instruction);
550 }
551
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100552 void VisitArraySet(HArraySet* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100553 HInstruction* array = instruction->InputAt(0);
554 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700555 DataType::Type type = instruction->GetComponentType();
556 VisitArrayAccess(array, index, type, HeapLocation::kScalar);
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100557 has_heap_stores_ = true;
558 }
559
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100560 void VisitVecLoad(HVecLoad* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100561 HInstruction* array = instruction->InputAt(0);
562 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700563 DataType::Type type = instruction->GetPackedType();
564 VisitArrayAccess(array, index, type, instruction->GetVectorLength());
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100565 CreateReferenceInfoForReferenceType(instruction);
566 }
567
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100568 void VisitVecStore(HVecStore* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100569 HInstruction* array = instruction->InputAt(0);
570 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700571 DataType::Type type = instruction->GetPackedType();
572 VisitArrayAccess(array, index, type, instruction->GetVectorLength());
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100573 has_heap_stores_ = true;
574 }
575
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100576 void VisitInstruction(HInstruction* instruction) override {
Mingyao Yangfef28842017-08-28 15:20:57 -0700577 // Any new-instance or new-array cannot alias with references that
578 // pre-exist the new-instance/new-array. We append entries into
579 // ref_info_array_ which keeps track of the order of creation
580 // of reference values since we visit the blocks in reverse post order.
581 //
582 // By default, VisitXXX() (including VisitPhi()) calls VisitInstruction(),
583 // unless VisitXXX() is overridden. VisitInstanceFieldGet() etc. above
584 // also call CreateReferenceInfoForReferenceType() explicitly.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100585 CreateReferenceInfoForReferenceType(instruction);
586 }
587
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100588 void VisitMonitorOperation(HMonitorOperation* monitor ATTRIBUTE_UNUSED) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100589 has_monitor_operations_ = true;
590 }
591
Vladimir Markoef898422020-06-08 10:26:06 +0100592 ScopedArenaAllocator* allocator_;
593 ScopedArenaVector<ReferenceInfo*> ref_info_array_; // All references used for heap accesses.
594 ScopedArenaVector<HeapLocation*> heap_locations_; // All heap locations.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100595 ArenaBitVector aliasing_matrix_; // aliasing info between each pair of locations.
596 bool has_heap_stores_; // If there is no heap stores, LSE acts as GVN with better
597 // alias analysis and won't be as effective.
598 bool has_volatile_; // If there are volatile field accesses.
599 bool has_monitor_operations_; // If there are monitor operations.
600
601 DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
602};
603
Vladimir Markoef898422020-06-08 10:26:06 +0100604class LoadStoreAnalysis {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100605 public:
Vladimir Markoef898422020-06-08 10:26:06 +0100606 explicit LoadStoreAnalysis(HGraph* graph, ScopedArenaAllocator* local_allocator)
607 : graph_(graph),
608 heap_location_collector_(graph, local_allocator) {}
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100609
610 const HeapLocationCollector& GetHeapLocationCollector() const {
611 return heap_location_collector_;
612 }
613
Vladimir Markoef898422020-06-08 10:26:06 +0100614 bool Run();
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100615
616 private:
Vladimir Markoef898422020-06-08 10:26:06 +0100617 HGraph* graph_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100618 HeapLocationCollector heap_location_collector_;
619
620 DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
621};
622
623} // namespace art
624
625#endif // ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_