blob: 08d9309a3e1f3348b424d58a10c74f8fc3cf90e3 [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,
Aart Bikb765a3f2018-05-10 14:47:48 -070097 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +010098 size_t offset,
99 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100100 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100101 int16_t declaring_class_def_index)
102 : ref_info_(ref_info),
Aart Bikb765a3f2018-05-10 14:47:48 -0700103 type_(DataType::ToSigned(type)),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100104 offset_(offset),
105 index_(index),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100106 vector_length_(vector_length),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100107 declaring_class_def_index_(declaring_class_def_index),
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700108 value_killed_by_loop_side_effects_(true),
109 has_aliased_locations_(false) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100110 DCHECK(ref_info != nullptr);
111 DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
112 (offset != kInvalidFieldOffset && index == nullptr));
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100113 if (ref_info->IsSingleton() && !IsArray()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100114 // Assume this location's value cannot be killed by loop side effects
115 // until proven otherwise.
116 value_killed_by_loop_side_effects_ = false;
117 }
118 }
119
120 ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
Aart Bikb765a3f2018-05-10 14:47:48 -0700121 DataType::Type GetType() const { return type_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100122 size_t GetOffset() const { return offset_; }
123 HInstruction* GetIndex() const { return index_; }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100124 size_t GetVectorLength() const { return vector_length_; }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100125
126 // Returns the definition of declaring class' dex index.
127 // It's kDeclaringClassDefIndexForArrays for an array element.
128 int16_t GetDeclaringClassDefIndex() const {
129 return declaring_class_def_index_;
130 }
131
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100132 bool IsArray() const {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100133 return index_ != nullptr;
134 }
135
136 bool IsValueKilledByLoopSideEffects() const {
137 return value_killed_by_loop_side_effects_;
138 }
139
140 void SetValueKilledByLoopSideEffects(bool val) {
141 value_killed_by_loop_side_effects_ = val;
142 }
143
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700144 bool HasAliasedLocations() const {
145 return has_aliased_locations_;
146 }
147
148 void SetHasAliasedLocations(bool val) {
149 has_aliased_locations_ = val;
150 }
151
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100152 private:
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100153 // Reference for instance/static field, array element or vector data.
154 ReferenceInfo* const ref_info_;
Aart Bikb765a3f2018-05-10 14:47:48 -0700155 // Type of data residing at HeapLocation (always signed for integral
156 // data since e.g. a[i] and a[i] & 0xff are represented by differently
157 // signed types; char vs short are disambiguated through the reference).
158 const DataType::Type type_;
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100159 // Offset of static/instance field.
160 // Invalid when this HeapLocation is not field.
161 const size_t offset_;
162 // Index of an array element or starting index of vector data.
163 // Invalid when this HeapLocation is not array.
164 HInstruction* const index_;
165 // Vector length of vector data.
166 // When this HeapLocation is not vector data, it's value is kScalar.
167 const size_t vector_length_;
168 // Declaring class's def's dex index.
169 // Invalid when this HeapLocation is not field access.
170 const int16_t declaring_class_def_index_;
171
172 // Value of this location may be killed by loop side effects
173 // because this location is stored into inside a loop.
174 // This gives better info on whether a singleton's location
175 // value may be killed by loop side effects.
176 bool value_killed_by_loop_side_effects_;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100177
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700178 // Has aliased heap locations in the method, due to either the
179 // reference is aliased or the array element is aliased via different
180 // index names.
181 bool has_aliased_locations_;
182
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100183 DISALLOW_COPY_AND_ASSIGN(HeapLocation);
184};
185
186// A HeapLocationCollector collects all relevant heap locations and keeps
187// an aliasing matrix for all locations.
188class HeapLocationCollector : public HGraphVisitor {
189 public:
190 static constexpr size_t kHeapLocationNotFound = -1;
191 // Start with a single uint32_t word. That's enough bits for pair-wise
192 // aliasing matrix of 8 heap locations.
193 static constexpr uint32_t kInitialAliasingMatrixBitVectorSize = 32;
194
195 explicit HeapLocationCollector(HGraph* graph)
196 : HGraphVisitor(graph),
Vladimir Marko009d1662017-10-10 13:21:15 +0100197 ref_info_array_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
198 heap_locations_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
Vladimir Markoca6fff82017-10-03 14:49:14 +0100199 aliasing_matrix_(graph->GetAllocator(),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100200 kInitialAliasingMatrixBitVectorSize,
201 true,
Vladimir Marko009d1662017-10-10 13:21:15 +0100202 kArenaAllocLSA),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100203 has_heap_stores_(false),
204 has_volatile_(false),
205 has_monitor_operations_(false) {}
206
207 void CleanUp() {
208 heap_locations_.clear();
209 ref_info_array_.clear();
210 }
211
212 size_t GetNumberOfHeapLocations() const {
213 return heap_locations_.size();
214 }
215
216 HeapLocation* GetHeapLocation(size_t index) const {
217 return heap_locations_[index];
218 }
219
220 HInstruction* HuntForOriginalReference(HInstruction* ref) const {
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000221 // An original reference can be transformed by instructions like:
222 // i0 NewArray
223 // i1 HInstruction(i0) <-- NullCheck, BoundType, IntermediateAddress.
224 // i2 ArrayGet(i1, index)
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100225 DCHECK(ref != nullptr);
xueliang.zhonge0eb4832017-10-30 13:43:14 +0000226 while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100227 ref = ref->InputAt(0);
228 }
229 return ref;
230 }
231
232 ReferenceInfo* FindReferenceInfoOf(HInstruction* ref) const {
233 for (size_t i = 0; i < ref_info_array_.size(); i++) {
234 ReferenceInfo* ref_info = ref_info_array_[i];
235 if (ref_info->GetReference() == ref) {
236 DCHECK_EQ(i, ref_info->GetPosition());
237 return ref_info;
238 }
239 }
240 return nullptr;
241 }
242
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100243 size_t GetFieldHeapLocation(HInstruction* object, const FieldInfo* field) const {
244 DCHECK(object != nullptr);
245 DCHECK(field != nullptr);
246 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(object)),
Aart Bikb765a3f2018-05-10 14:47:48 -0700247 field->GetFieldType(),
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100248 field->GetFieldOffset().SizeValue(),
249 nullptr,
250 HeapLocation::kScalar,
251 field->GetDeclaringClassDefIndex());
252 }
253
Aart Bikb765a3f2018-05-10 14:47:48 -0700254 size_t GetArrayHeapLocation(HInstruction* instruction) const {
255 DCHECK(instruction != nullptr);
256 HInstruction* array = instruction->InputAt(0);
257 HInstruction* index = instruction->InputAt(1);
258 DataType::Type type = instruction->GetType();
259 size_t vector_length = HeapLocation::kScalar;
260 if (instruction->IsArraySet()) {
261 type = instruction->AsArraySet()->GetComponentType();
262 } else if (instruction->IsVecStore() ||
263 instruction->IsVecLoad()) {
264 HVecOperation* vec_op = instruction->AsVecOperation();
265 type = vec_op->GetPackedType();
266 vector_length = vec_op->GetVectorLength();
267 } else {
268 DCHECK(instruction->IsArrayGet());
269 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100270 return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
Aart Bikb765a3f2018-05-10 14:47:48 -0700271 type,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100272 HeapLocation::kInvalidFieldOffset,
273 index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100274 vector_length,
xueliang.zhong016c0f12017-05-12 18:16:31 +0100275 HeapLocation::kDeclaringClassDefIndexForArrays);
276 }
277
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100278 bool HasHeapStores() const {
279 return has_heap_stores_;
280 }
281
282 bool HasVolatile() const {
283 return has_volatile_;
284 }
285
286 bool HasMonitorOps() const {
287 return has_monitor_operations_;
288 }
289
290 // Find and return the heap location index in heap_locations_.
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100291 // NOTE: When heap locations are created, potentially aliasing/overlapping
292 // accesses are given different indexes. This find function also
293 // doesn't take aliasing/overlapping into account. For example,
294 // this function returns three different indexes for:
295 // - ref_info=array, index=i, vector_length=kScalar;
296 // - ref_info=array, index=i, vector_length=2;
297 // - ref_info=array, index=i, vector_length=4;
298 // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
299 // these indexes alias.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100300 size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
Aart Bikb765a3f2018-05-10 14:47:48 -0700301 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100302 size_t offset,
303 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100304 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100305 int16_t declaring_class_def_index) const {
Aart Bikb765a3f2018-05-10 14:47:48 -0700306 DataType::Type lookup_type = DataType::ToSigned(type);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100307 for (size_t i = 0; i < heap_locations_.size(); i++) {
308 HeapLocation* loc = heap_locations_[i];
309 if (loc->GetReferenceInfo() == ref_info &&
Aart Bikb765a3f2018-05-10 14:47:48 -0700310 loc->GetType() == lookup_type &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100311 loc->GetOffset() == offset &&
312 loc->GetIndex() == index &&
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100313 loc->GetVectorLength() == vector_length &&
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100314 loc->GetDeclaringClassDefIndex() == declaring_class_def_index) {
315 return i;
316 }
317 }
318 return kHeapLocationNotFound;
319 }
320
321 // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
322 bool MayAlias(size_t index1, size_t index2) const {
323 if (index1 < index2) {
324 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index1, index2));
325 } else if (index1 > index2) {
326 return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index2, index1));
327 } else {
328 DCHECK(false) << "index1 and index2 are expected to be different";
329 return true;
330 }
331 }
332
333 void BuildAliasingMatrix() {
334 const size_t number_of_locations = heap_locations_.size();
335 if (number_of_locations == 0) {
336 return;
337 }
338 size_t pos = 0;
339 // Compute aliasing info between every pair of different heap locations.
340 // Save the result in a matrix represented as a BitVector.
341 for (size_t i = 0; i < number_of_locations - 1; i++) {
342 for (size_t j = i + 1; j < number_of_locations; j++) {
343 if (ComputeMayAlias(i, j)) {
344 aliasing_matrix_.SetBit(CheckedAliasingMatrixPosition(i, j, pos));
345 }
346 pos++;
347 }
348 }
349 }
350
351 private:
352 // An allocation cannot alias with a name which already exists at the point
353 // of the allocation, such as a parameter or a load happening before the allocation.
354 bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
355 if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
356 // Any reference that can alias with the allocation must appear after it in the block/in
357 // the block's successors. In reverse post order, those instructions will be visited after
358 // the allocation.
359 return ref_info2->GetPosition() >= ref_info1->GetPosition();
360 }
361 return true;
362 }
363
364 bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
365 if (ref_info1 == ref_info2) {
366 return true;
367 } else if (ref_info1->IsSingleton()) {
368 return false;
369 } else if (ref_info2->IsSingleton()) {
370 return false;
371 } else if (!MayAliasWithPreexistenceChecking(ref_info1, ref_info2) ||
372 !MayAliasWithPreexistenceChecking(ref_info2, ref_info1)) {
373 return false;
374 }
375 return true;
376 }
377
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100378 bool CanArrayElementsAlias(const HInstruction* idx1,
379 const size_t vector_length1,
380 const HInstruction* idx2,
381 const size_t vector_length2) const;
xueliang.zhong016c0f12017-05-12 18:16:31 +0100382
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100383 // `index1` and `index2` are indices in the array of collected heap locations.
384 // Returns the position in the bit vector that tracks whether the two heap
385 // locations may alias.
386 size_t AliasingMatrixPosition(size_t index1, size_t index2) const {
387 DCHECK(index2 > index1);
388 const size_t number_of_locations = heap_locations_.size();
389 // It's (num_of_locations - 1) + ... + (num_of_locations - index1) + (index2 - index1 - 1).
390 return (number_of_locations * index1 - (1 + index1) * index1 / 2 + (index2 - index1 - 1));
391 }
392
393 // An additional position is passed in to make sure the calculated position is correct.
394 size_t CheckedAliasingMatrixPosition(size_t index1, size_t index2, size_t position) {
395 size_t calculated_position = AliasingMatrixPosition(index1, index2);
396 DCHECK_EQ(calculated_position, position);
397 return calculated_position;
398 }
399
400 // Compute if two locations may alias to each other.
401 bool ComputeMayAlias(size_t index1, size_t index2) const {
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700402 DCHECK_NE(index1, index2);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100403 HeapLocation* loc1 = heap_locations_[index1];
404 HeapLocation* loc2 = heap_locations_[index2];
405 if (loc1->GetOffset() != loc2->GetOffset()) {
406 // Either two different instance fields, or one is an instance
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100407 // field and the other is an array data.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100408 return false;
409 }
410 if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
411 // Different types.
412 return false;
413 }
414 if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
415 return false;
416 }
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100417 if (loc1->IsArray() && loc2->IsArray()) {
418 HInstruction* idx1 = loc1->GetIndex();
419 HInstruction* idx2 = loc2->GetIndex();
420 size_t vector_length1 = loc1->GetVectorLength();
421 size_t vector_length2 = loc2->GetVectorLength();
422 if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100423 return false;
424 }
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100425 }
Mingyao Yang0e3151b2017-10-30 11:19:57 -0700426 loc1->SetHasAliasedLocations(true);
427 loc2->SetHasAliasedLocations(true);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100428 return true;
429 }
430
431 ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
432 ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
433 if (ref_info == nullptr) {
434 size_t pos = ref_info_array_.size();
Vladimir Markoca6fff82017-10-03 14:49:14 +0100435 ref_info = new (GetGraph()->GetAllocator()) ReferenceInfo(instruction, pos);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100436 ref_info_array_.push_back(ref_info);
437 }
438 return ref_info;
439 }
440
441 void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100442 if (instruction->GetType() != DataType::Type::kReference) {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100443 return;
444 }
445 DCHECK(FindReferenceInfoOf(instruction) == nullptr);
446 GetOrCreateReferenceInfo(instruction);
447 }
448
449 HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
Aart Bikb765a3f2018-05-10 14:47:48 -0700450 DataType::Type type,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100451 size_t offset,
452 HInstruction* index,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100453 size_t vector_length,
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100454 int16_t declaring_class_def_index) {
455 HInstruction* original_ref = HuntForOriginalReference(ref);
456 ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
457 size_t heap_location_idx = FindHeapLocationIndex(
Aart Bikb765a3f2018-05-10 14:47:48 -0700458 ref_info, type, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100459 if (heap_location_idx == kHeapLocationNotFound) {
Vladimir Markoca6fff82017-10-03 14:49:14 +0100460 HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
Aart Bikb765a3f2018-05-10 14:47:48 -0700461 HeapLocation(ref_info, type, offset, index, vector_length, declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100462 heap_locations_.push_back(heap_loc);
463 return heap_loc;
464 }
465 return heap_locations_[heap_location_idx];
466 }
467
468 HeapLocation* VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
469 if (field_info.IsVolatile()) {
470 has_volatile_ = true;
471 }
Aart Bikb765a3f2018-05-10 14:47:48 -0700472 DataType::Type type = field_info.GetFieldType();
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100473 const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
474 const size_t offset = field_info.GetFieldOffset().SizeValue();
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100475 return GetOrCreateHeapLocation(ref,
Aart Bikb765a3f2018-05-10 14:47:48 -0700476 type,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100477 offset,
478 nullptr,
479 HeapLocation::kScalar,
480 declaring_class_def_index);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100481 }
482
Aart Bikb765a3f2018-05-10 14:47:48 -0700483 void VisitArrayAccess(HInstruction* array,
484 HInstruction* index,
485 DataType::Type type,
486 size_t vector_length) {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100487 GetOrCreateHeapLocation(array,
Aart Bikb765a3f2018-05-10 14:47:48 -0700488 type,
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100489 HeapLocation::kInvalidFieldOffset,
490 index,
491 vector_length,
492 HeapLocation::kDeclaringClassDefIndexForArrays);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100493 }
494
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100495 void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100496 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
497 CreateReferenceInfoForReferenceType(instruction);
498 }
499
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100500 void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100501 HeapLocation* location = VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
502 has_heap_stores_ = true;
503 if (location->GetReferenceInfo()->IsSingleton()) {
504 // A singleton's location value may be killed by loop side effects if it's
505 // defined before that loop, and it's stored into inside that loop.
506 HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
507 if (loop_info != nullptr) {
508 HInstruction* ref = location->GetReferenceInfo()->GetReference();
509 DCHECK(ref->IsNewInstance());
510 if (loop_info->IsDefinedOutOfTheLoop(ref)) {
511 // ref's location value may be killed by this loop's side effects.
512 location->SetValueKilledByLoopSideEffects(true);
513 } else {
514 // ref is defined inside this loop so this loop's side effects cannot
515 // kill its location value at the loop header since ref/its location doesn't
516 // exist yet at the loop header.
517 }
518 }
519 } else {
520 // For non-singletons, value_killed_by_loop_side_effects_ is inited to
521 // true.
522 DCHECK_EQ(location->IsValueKilledByLoopSideEffects(), true);
523 }
524 }
525
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100526 void VisitStaticFieldGet(HStaticFieldGet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100527 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
528 CreateReferenceInfoForReferenceType(instruction);
529 }
530
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100531 void VisitStaticFieldSet(HStaticFieldSet* instruction) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100532 VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
533 has_heap_stores_ = true;
534 }
535
536 // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
537 // since we cannot accurately track the fields.
538
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100539 void VisitArrayGet(HArrayGet* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100540 HInstruction* array = instruction->InputAt(0);
541 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700542 DataType::Type type = instruction->GetType();
543 VisitArrayAccess(array, index, type, HeapLocation::kScalar);
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100544 CreateReferenceInfoForReferenceType(instruction);
545 }
546
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100547 void VisitArraySet(HArraySet* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100548 HInstruction* array = instruction->InputAt(0);
549 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700550 DataType::Type type = instruction->GetComponentType();
551 VisitArrayAccess(array, index, type, HeapLocation::kScalar);
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100552 has_heap_stores_ = true;
553 }
554
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100555 void VisitVecLoad(HVecLoad* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100556 HInstruction* array = instruction->InputAt(0);
557 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700558 DataType::Type type = instruction->GetPackedType();
559 VisitArrayAccess(array, index, type, instruction->GetVectorLength());
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100560 CreateReferenceInfoForReferenceType(instruction);
561 }
562
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100563 void VisitVecStore(HVecStore* instruction) override {
xueliang.zhongb50b16a2017-09-19 17:43:29 +0100564 HInstruction* array = instruction->InputAt(0);
565 HInstruction* index = instruction->InputAt(1);
Aart Bikb765a3f2018-05-10 14:47:48 -0700566 DataType::Type type = instruction->GetPackedType();
567 VisitArrayAccess(array, index, type, instruction->GetVectorLength());
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100568 has_heap_stores_ = true;
569 }
570
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100571 void VisitInstruction(HInstruction* instruction) override {
Mingyao Yangfef28842017-08-28 15:20:57 -0700572 // Any new-instance or new-array cannot alias with references that
573 // pre-exist the new-instance/new-array. We append entries into
574 // ref_info_array_ which keeps track of the order of creation
575 // of reference values since we visit the blocks in reverse post order.
576 //
577 // By default, VisitXXX() (including VisitPhi()) calls VisitInstruction(),
578 // unless VisitXXX() is overridden. VisitInstanceFieldGet() etc. above
579 // also call CreateReferenceInfoForReferenceType() explicitly.
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100580 CreateReferenceInfoForReferenceType(instruction);
581 }
582
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100583 void VisitMonitorOperation(HMonitorOperation* monitor ATTRIBUTE_UNUSED) override {
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100584 has_monitor_operations_ = true;
585 }
586
587 ArenaVector<ReferenceInfo*> ref_info_array_; // All references used for heap accesses.
588 ArenaVector<HeapLocation*> heap_locations_; // All heap locations.
589 ArenaBitVector aliasing_matrix_; // aliasing info between each pair of locations.
590 bool has_heap_stores_; // If there is no heap stores, LSE acts as GVN with better
591 // alias analysis and won't be as effective.
592 bool has_volatile_; // If there are volatile field accesses.
593 bool has_monitor_operations_; // If there are monitor operations.
594
595 DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
596};
597
598class LoadStoreAnalysis : public HOptimization {
599 public:
Aart Bik2ca10eb2017-11-15 15:17:53 -0800600 explicit LoadStoreAnalysis(HGraph* graph, const char* name = kLoadStoreAnalysisPassName)
601 : HOptimization(graph, name),
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100602 heap_location_collector_(graph) {}
603
604 const HeapLocationCollector& GetHeapLocationCollector() const {
605 return heap_location_collector_;
606 }
607
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100608 bool Run() override;
xueliang.zhongc239a2b2017-04-27 15:31:37 +0100609
610 static constexpr const char* kLoadStoreAnalysisPassName = "load_store_analysis";
611
612 private:
613 HeapLocationCollector heap_location_collector_;
614
615 DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
616};
617
618} // namespace art
619
620#endif // ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_