• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "base/arena_allocator.h"
21 #include "base/arena_bit_vector.h"
22 #include "base/bit_vector-inl.h"
23 #include "base/macros.h"
24 #include "base/scoped_arena_allocator.h"
25 #include "base/scoped_arena_containers.h"
26 #include "base/stl_util.h"
27 #include "escape.h"
28 #include "nodes.h"
29 #include "optimizing/optimizing_compiler_stats.h"
30 
31 namespace art HIDDEN {
32 
33 // A ReferenceInfo contains additional info about a reference such as
34 // whether it's a singleton, returned, etc.
35 class ReferenceInfo : public DeletableArenaObject<kArenaAllocLSA> {
36  public:
ReferenceInfo(HInstruction * reference,size_t pos)37   ReferenceInfo(HInstruction* reference, size_t pos)
38       : reference_(reference),
39         position_(pos),
40         is_singleton_(true),
41         is_singleton_and_not_returned_(true),
42         is_singleton_and_not_deopt_visible_(true) {
43     CalculateEscape(reference_,
44                     nullptr,
45                     &is_singleton_,
46                     &is_singleton_and_not_returned_,
47                     &is_singleton_and_not_deopt_visible_);
48   }
49 
GetReference()50   HInstruction* GetReference() const {
51     return reference_;
52   }
53 
GetPosition()54   size_t GetPosition() const {
55     return position_;
56   }
57 
58   // Returns true if reference_ is the only name that can refer to its value during
59   // the lifetime of the method. So it's guaranteed to not have any alias in
60   // the method (including its callees).
IsSingleton()61   bool IsSingleton() const {
62     return is_singleton_;
63   }
64 
65   // Returns true if reference_ is a singleton and not returned to the caller or
66   // used as an environment local of an HDeoptimize instruction.
67   // The allocation and stores into reference_ may be eliminated for such cases.
IsSingletonAndRemovable()68   bool IsSingletonAndRemovable() const {
69     return is_singleton_and_not_returned_ && is_singleton_and_not_deopt_visible_;
70   }
71 
72   // Returns true if reference_ is a singleton and returned to the caller or
73   // used as an environment local of an HDeoptimize instruction.
IsSingletonAndNonRemovable()74   bool IsSingletonAndNonRemovable() const {
75     return is_singleton_ &&
76            (!is_singleton_and_not_returned_ || !is_singleton_and_not_deopt_visible_);
77   }
78 
79  private:
80   HInstruction* const reference_;
81   // Position in which it was inserted into the ref_infos_ vector. A smaller number means that this
82   // reference was seen before a reference with a bigger number.
83   const size_t position_;
84 
85   // Can only be referred to by a single name in the method.
86   bool is_singleton_;
87   // Is singleton and not returned to caller.
88   bool is_singleton_and_not_returned_;
89   // Is singleton and not used as an environment local of HDeoptimize.
90   bool is_singleton_and_not_deopt_visible_;
91 
92   DISALLOW_COPY_AND_ASSIGN(ReferenceInfo);
93 };
94 
95 // A heap location is a reference-offset/index pair that a value can be loaded from
96 // or stored to.
97 class HeapLocation : public ArenaObject<kArenaAllocLSA> {
98  public:
99   static constexpr size_t kInvalidFieldOffset = -1;
100   // Default value for heap locations which are not vector data.
101   static constexpr size_t kScalar = 1;
102   // TODO: more fine-grained array types.
103   static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
104 
HeapLocation(ReferenceInfo * ref_info,DataType::Type type,size_t offset,HInstruction * index,size_t vector_length,int16_t declaring_class_def_index,bool is_vec_op)105   HeapLocation(ReferenceInfo* ref_info,
106                DataType::Type type,
107                size_t offset,
108                HInstruction* index,
109                size_t vector_length,
110                int16_t declaring_class_def_index,
111                bool is_vec_op)
112       : ref_info_(ref_info),
113         type_(DataType::ToSigned(type)),
114         offset_(offset),
115         index_(index),
116         vector_length_(vector_length),
117         declaring_class_def_index_(declaring_class_def_index),
118         has_aliased_locations_(false),
119         is_vec_op_(is_vec_op) {
120     DCHECK(ref_info != nullptr);
121     DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
122            (offset != kInvalidFieldOffset && index == nullptr));
123   }
124 
GetReferenceInfo()125   ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
GetType()126   DataType::Type GetType() const { return type_; }
GetOffset()127   size_t GetOffset() const { return offset_; }
GetIndex()128   HInstruction* GetIndex() const { return index_; }
GetVectorLength()129   size_t GetVectorLength() const { return vector_length_; }
IsVecOp()130   bool IsVecOp() const { return is_vec_op_; }
131 
132   // Returns the definition of declaring class' dex index.
133   // It's kDeclaringClassDefIndexForArrays for an array element.
GetDeclaringClassDefIndex()134   int16_t GetDeclaringClassDefIndex() const {
135     return declaring_class_def_index_;
136   }
137 
IsArray()138   bool IsArray() const {
139     return index_ != nullptr;
140   }
141 
HasAliasedLocations()142   bool HasAliasedLocations() const {
143     return has_aliased_locations_;
144   }
145 
SetHasAliasedLocations(bool val)146   void SetHasAliasedLocations(bool val) {
147     has_aliased_locations_ = val;
148   }
149 
150  private:
151   // Reference for instance/static field, array element or vector data.
152   ReferenceInfo* const ref_info_;
153   // Type of data residing at HeapLocation (always signed for integral
154   // data since e.g. a[i] and a[i] & 0xff are represented by differently
155   // signed types; char vs short are disambiguated through the reference).
156   const DataType::Type type_;
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   // Has aliased heap locations in the method, due to either the
170   // reference is aliased or the array element is aliased via different
171   // index names.
172   bool has_aliased_locations_;
173   // Whether this HeapLocation represents a vector operation.
174   bool is_vec_op_;
175 
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.
181 class HeapLocationCollector final : 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 
HeapLocationCollector(HGraph * graph,ScopedArenaAllocator * allocator)188   HeapLocationCollector(HGraph* graph, ScopedArenaAllocator* allocator)
189       : HGraphVisitor(graph),
190         allocator_(allocator),
191         ref_infos_(graph->GetCurrentInstructionId(), nullptr, allocator->Adapter(kArenaAllocLSA)),
192         ref_infos_created_(0u),
193         heap_locations_(allocator->Adapter(kArenaAllocLSA)),
194         aliasing_matrix_(allocator, kInitialAliasingMatrixBitVectorSize, true, kArenaAllocLSA),
195         has_heap_stores_(false) {}
196 
~HeapLocationCollector()197   ~HeapLocationCollector() {
198     CleanUp();
199   }
200 
CleanUp()201   void CleanUp() {
202     heap_locations_.clear();
203     STLDeleteContainerPointers(ref_infos_.begin(), ref_infos_.end());
204     ref_infos_.clear();
205   }
206 
GetNumberOfHeapLocations()207   size_t GetNumberOfHeapLocations() const {
208     return heap_locations_.size();
209   }
210 
GetHeapLocation(size_t index)211   HeapLocation* GetHeapLocation(size_t index) const {
212     return heap_locations_[index];
213   }
214 
GetHeapLocationIndex(const HeapLocation * hl)215   size_t GetHeapLocationIndex(const HeapLocation* hl) const {
216     auto res = std::find(heap_locations_.cbegin(), heap_locations_.cend(), hl);
217     return std::distance(heap_locations_.cbegin(), res);
218   }
219 
HuntForOriginalReference(HInstruction * ref)220   HInstruction* HuntForOriginalReference(HInstruction* ref) const {
221     // An original reference can be transformed by instructions like:
222     //   i0 NewArray
223     //   i1 HInstruction(i0)  <-- NullCheck, BoundType, IntermediateAddress.
224     //   i2 ArrayGet(i1, index)
225     DCHECK(ref != nullptr);
226     while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
227       ref = ref->InputAt(0);
228     }
229     return ref;
230   }
231 
FindReferenceInfoOf(HInstruction * ref)232   ReferenceInfo* FindReferenceInfoOf(HInstruction* ref) const {
233     return ref_infos_[ref->GetId()];
234   }
235 
GetFieldHeapLocation(HInstruction * object,const FieldInfo * field)236   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->GetFieldType(),
241                                  field->GetFieldOffset().SizeValue(),
242                                  nullptr,
243                                  HeapLocation::kScalar,
244                                  field->GetDeclaringClassDefIndex(),
245                                  /*is_vec_op=*/false);
246   }
247 
GetArrayHeapLocation(HInstruction * instruction)248   size_t GetArrayHeapLocation(HInstruction* instruction) const {
249     DCHECK(instruction != nullptr);
250     HInstruction* array = instruction->InputAt(0);
251     HInstruction* index = instruction->InputAt(1);
252     DataType::Type type = instruction->GetType();
253     size_t vector_length = HeapLocation::kScalar;
254     const bool is_vec_op = instruction->IsVecStore() || instruction->IsVecLoad();
255     if (instruction->IsArraySet()) {
256       type = instruction->AsArraySet()->GetComponentType();
257     } else if (is_vec_op) {
258       HVecOperation* vec_op = instruction->AsVecOperation();
259       type = vec_op->GetPackedType();
260       vector_length = vec_op->GetVectorLength();
261     } else {
262       DCHECK(instruction->IsArrayGet());
263     }
264     return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
265                                  type,
266                                  HeapLocation::kInvalidFieldOffset,
267                                  index,
268                                  vector_length,
269                                  HeapLocation::kDeclaringClassDefIndexForArrays,
270                                  is_vec_op);
271   }
272 
HasHeapStores()273   bool HasHeapStores() const {
274     return has_heap_stores_;
275   }
276 
277   // Find and return the heap location index in heap_locations_.
278   // NOTE: When heap locations are created, potentially aliasing/overlapping
279   // accesses are given different indexes. This find function also
280   // doesn't take aliasing/overlapping into account. For example,
281   // this function returns three different indexes for:
282   // - ref_info=array, index=i, vector_length=kScalar;
283   // - ref_info=array, index=i, vector_length=2;
284   // - ref_info=array, index=i, vector_length=4;
285   // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
286   // these indexes alias.
FindHeapLocationIndex(ReferenceInfo * ref_info,DataType::Type type,size_t offset,HInstruction * index,size_t vector_length,int16_t declaring_class_def_index,bool is_vec_op)287   size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
288                                DataType::Type type,
289                                size_t offset,
290                                HInstruction* index,
291                                size_t vector_length,
292                                int16_t declaring_class_def_index,
293                                bool is_vec_op) const {
294     DataType::Type lookup_type = DataType::ToSigned(type);
295     for (size_t i = 0; i < heap_locations_.size(); i++) {
296       HeapLocation* loc = heap_locations_[i];
297       if (loc->GetReferenceInfo() == ref_info &&
298           loc->GetType() == lookup_type &&
299           loc->GetOffset() == offset &&
300           loc->GetIndex() == index &&
301           loc->GetVectorLength() == vector_length &&
302           loc->GetDeclaringClassDefIndex() == declaring_class_def_index &&
303           loc->IsVecOp() == is_vec_op) {
304         return i;
305       }
306     }
307     return kHeapLocationNotFound;
308   }
309 
310   bool InstructionEligibleForLSERemoval(HInstruction* inst) const;
311 
312   // Get some estimated statistics based on our analysis.
313   void DumpReferenceStats(OptimizingCompilerStats* stats);
314 
315   // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
MayAlias(size_t index1,size_t index2)316   bool MayAlias(size_t index1, size_t index2) const {
317     if (index1 < index2) {
318       return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index1, index2));
319     } else if (index1 > index2) {
320       return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index2, index1));
321     } else {
322       DCHECK(false) << "index1 and index2 are expected to be different";
323       return true;
324     }
325   }
326 
BuildAliasingMatrix()327   void BuildAliasingMatrix() {
328     const size_t number_of_locations = heap_locations_.size();
329     if (number_of_locations == 0) {
330       return;
331     }
332     size_t pos = 0;
333     // Compute aliasing info between every pair of different heap locations.
334     // Save the result in a matrix represented as a BitVector.
335     for (size_t i = 0; i < number_of_locations - 1; i++) {
336       for (size_t j = i + 1; j < number_of_locations; j++) {
337         if (ComputeMayAlias(i, j)) {
338           aliasing_matrix_.SetBit(CheckedAliasingMatrixPosition(i, j, pos));
339         }
340         pos++;
341       }
342     }
343   }
344 
CanReferencesAlias(ReferenceInfo * ref_info1,ReferenceInfo * ref_info2)345   static bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) {
346     if (ref_info1 == ref_info2) {
347       return true;
348     } else if (ref_info1->IsSingleton()) {
349       return false;
350     } else if (ref_info2->IsSingleton()) {
351       return false;
352     } else if (!MayAliasWithPreexistenceChecking(ref_info1, ref_info2) ||
353         !MayAliasWithPreexistenceChecking(ref_info2, ref_info1)) {
354       return false;
355     }
356     return true;
357   }
358 
359  private:
360   // An allocation cannot alias with a name which already exists at the point
361   // of the allocation, such as a parameter or a load happening before the allocation.
MayAliasWithPreexistenceChecking(ReferenceInfo * ref_info1,ReferenceInfo * ref_info2)362   static bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) {
363     if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
364       // Any reference that can alias with the allocation must appear after it in the block/in
365       // the block's successors. In reverse post order, those instructions will be visited after
366       // the allocation.
367       return ref_info2->GetPosition() >= ref_info1->GetPosition();
368     }
369     return true;
370   }
371 
372   bool CanArrayElementsAlias(const HInstruction* idx1,
373                              const size_t vector_length1,
374                              const HInstruction* idx2,
375                              const size_t vector_length2) const;
376 
377   // `index1` and `index2` are indices in the array of collected heap locations.
378   // Returns the position in the bit vector that tracks whether the two heap
379   // locations may alias.
AliasingMatrixPosition(size_t index1,size_t index2)380   size_t AliasingMatrixPosition(size_t index1, size_t index2) const {
381     DCHECK(index2 > index1);
382     const size_t number_of_locations = heap_locations_.size();
383     // It's (num_of_locations - 1) + ... + (num_of_locations - index1) + (index2 - index1 - 1).
384     return (number_of_locations * index1 - (1 + index1) * index1 / 2 + (index2 - index1 - 1));
385   }
386 
387   // An additional position is passed in to make sure the calculated position is correct.
CheckedAliasingMatrixPosition(size_t index1,size_t index2,size_t position)388   size_t CheckedAliasingMatrixPosition(size_t index1, size_t index2, size_t position) {
389     size_t calculated_position = AliasingMatrixPosition(index1, index2);
390     DCHECK_EQ(calculated_position, position);
391     return calculated_position;
392   }
393 
394   // Compute if two locations may alias to each other.
ComputeMayAlias(size_t index1,size_t index2)395   bool ComputeMayAlias(size_t index1, size_t index2) const {
396     DCHECK_NE(index1, index2);
397     HeapLocation* loc1 = heap_locations_[index1];
398     HeapLocation* loc2 = heap_locations_[index2];
399     if (loc1->GetOffset() != loc2->GetOffset()) {
400       // Either two different instance fields, or one is an instance
401       // field and the other is an array data.
402       return false;
403     }
404     if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
405       // Different types.
406       return false;
407     }
408     if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
409       return false;
410     }
411     if (loc1->IsArray() && loc2->IsArray()) {
412       HInstruction* idx1 = loc1->GetIndex();
413       HInstruction* idx2 = loc2->GetIndex();
414       size_t vector_length1 = loc1->GetVectorLength();
415       size_t vector_length2 = loc2->GetVectorLength();
416       if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
417         return false;
418       }
419     }
420     loc1->SetHasAliasedLocations(true);
421     loc2->SetHasAliasedLocations(true);
422     return true;
423   }
424 
GetOrCreateReferenceInfo(HInstruction * instruction)425   ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
426     ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
427     if (ref_info == nullptr) {
428       ref_info = new (allocator_) ReferenceInfo(instruction, ref_infos_created_);
429       ref_infos_created_++;
430       ref_infos_[instruction->GetId()] = ref_info;
431     }
432     return ref_info;
433   }
434 
CreateReferenceInfoForReferenceType(HInstruction * instruction)435   void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
436     if (instruction->GetType() != DataType::Type::kReference) {
437       return;
438     }
439     DCHECK(FindReferenceInfoOf(instruction) == nullptr);
440     GetOrCreateReferenceInfo(instruction);
441   }
442 
MaybeCreateHeapLocation(HInstruction * ref,DataType::Type type,size_t offset,HInstruction * index,size_t vector_length,int16_t declaring_class_def_index,bool is_vec_op)443   void MaybeCreateHeapLocation(HInstruction* ref,
444                                DataType::Type type,
445                                size_t offset,
446                                HInstruction* index,
447                                size_t vector_length,
448                                int16_t declaring_class_def_index,
449                                bool is_vec_op) {
450     HInstruction* original_ref = HuntForOriginalReference(ref);
451     ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
452     size_t heap_location_idx = FindHeapLocationIndex(
453         ref_info, type, offset, index, vector_length, declaring_class_def_index, is_vec_op);
454     if (heap_location_idx == kHeapLocationNotFound) {
455       HeapLocation* heap_loc = new (allocator_) HeapLocation(
456           ref_info, type, offset, index, vector_length, declaring_class_def_index, is_vec_op);
457       heap_locations_.push_back(heap_loc);
458     }
459   }
460 
VisitFieldAccess(HFieldAccess * instruction)461   void VisitFieldAccess(HFieldAccess* instruction) override {
462     HInstruction* ref = instruction->InputAt(0);
463     const FieldInfo& field_info = instruction->GetFieldInfo();
464     DataType::Type type = field_info.GetFieldType();
465     const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
466     const size_t offset = field_info.GetFieldOffset().SizeValue();
467     MaybeCreateHeapLocation(ref,
468                             type,
469                             offset,
470                             nullptr,
471                             HeapLocation::kScalar,
472                             declaring_class_def_index,
473                             /*is_vec_op=*/false);
474   }
475 
VisitArrayAccess(HInstruction * array,HInstruction * index,DataType::Type type,size_t vector_length,bool is_vec_op)476   void VisitArrayAccess(HInstruction* array,
477                         HInstruction* index,
478                         DataType::Type type,
479                         size_t vector_length,
480                         bool is_vec_op) {
481     MaybeCreateHeapLocation(array,
482                             type,
483                             HeapLocation::kInvalidFieldOffset,
484                             index,
485                             vector_length,
486                             HeapLocation::kDeclaringClassDefIndexForArrays,
487                             is_vec_op);
488   }
489 
VisitInstanceFieldGet(HInstanceFieldGet * instruction)490   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) override {
491     CreateReferenceInfoForReferenceType(instruction);
492     VisitFieldAccess(instruction);
493   }
494 
VisitInstanceFieldSet(HInstanceFieldSet * instruction)495   void VisitInstanceFieldSet(HInstanceFieldSet* instruction) override {
496     has_heap_stores_ = true;
497     VisitFieldAccess(instruction);
498   }
499 
VisitStaticFieldGet(HStaticFieldGet * instruction)500   void VisitStaticFieldGet(HStaticFieldGet* instruction) override {
501     CreateReferenceInfoForReferenceType(instruction);
502     VisitFieldAccess(instruction);
503   }
504 
VisitStaticFieldSet(HStaticFieldSet * instruction)505   void VisitStaticFieldSet(HStaticFieldSet* instruction) override {
506     has_heap_stores_ = true;
507     VisitFieldAccess(instruction);
508   }
509 
510   // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
511   // since we cannot accurately track the fields.
512 
VisitArrayGet(HArrayGet * instruction)513   void VisitArrayGet(HArrayGet* instruction) override {
514     HInstruction* array = instruction->InputAt(0);
515     HInstruction* index = instruction->InputAt(1);
516     DataType::Type type = instruction->GetType();
517     VisitArrayAccess(array, index, type, HeapLocation::kScalar, /*is_vec_op=*/false);
518     CreateReferenceInfoForReferenceType(instruction);
519   }
520 
VisitArraySet(HArraySet * instruction)521   void VisitArraySet(HArraySet* instruction) override {
522     HInstruction* array = instruction->InputAt(0);
523     HInstruction* index = instruction->InputAt(1);
524     DataType::Type type = instruction->GetComponentType();
525     VisitArrayAccess(array, index, type, HeapLocation::kScalar, /*is_vec_op=*/false);
526     has_heap_stores_ = true;
527   }
528 
VisitVecLoad(HVecLoad * instruction)529   void VisitVecLoad(HVecLoad* instruction) override {
530     DCHECK(!instruction->IsPredicated());
531     HInstruction* array = instruction->InputAt(0);
532     HInstruction* index = instruction->InputAt(1);
533     DataType::Type type = instruction->GetPackedType();
534     VisitArrayAccess(array, index, type, instruction->GetVectorLength(), /*is_vec_op=*/true);
535     CreateReferenceInfoForReferenceType(instruction);
536   }
537 
VisitVecStore(HVecStore * instruction)538   void VisitVecStore(HVecStore* instruction) override {
539     DCHECK(!instruction->IsPredicated());
540     HInstruction* array = instruction->InputAt(0);
541     HInstruction* index = instruction->InputAt(1);
542     DataType::Type type = instruction->GetPackedType();
543     VisitArrayAccess(array, index, type, instruction->GetVectorLength(), /*is_vec_op=*/true);
544     has_heap_stores_ = true;
545   }
546 
VisitInstruction(HInstruction * instruction)547   void VisitInstruction(HInstruction* instruction) override {
548     // Any new-instance or new-array cannot alias with references that
549     // pre-exist the new-instance/new-array. The entries of ref_infos_ keep track of the order of
550     // creation of reference values since we visit the blocks in reverse post order.
551     //
552     // By default, VisitXXX() (including VisitPhi()) calls VisitInstruction(),
553     // unless VisitXXX() is overridden. VisitInstanceFieldGet() etc. above
554     // also call CreateReferenceInfoForReferenceType() explicitly.
555     CreateReferenceInfoForReferenceType(instruction);
556   }
557 
558   ScopedArenaAllocator* allocator_;
559   // All references used for heap accesses, accessed via instruction id.
560   ScopedArenaVector<ReferenceInfo*> ref_infos_;
561   // How many non-null ReferenceInfo* are in ref_infos_.
562   size_t ref_infos_created_;
563   ScopedArenaVector<HeapLocation*> heap_locations_;    // All heap locations.
564   ArenaBitVector aliasing_matrix_;    // aliasing info between each pair of locations.
565   bool has_heap_stores_;    // If there is no heap stores, LSE acts as GVN with better
566                             // alias analysis and won't be as effective.
567 
568   DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
569 };
570 
571 class LoadStoreAnalysis {
572  public:
LoadStoreAnalysis(HGraph * graph,OptimizingCompilerStats * stats,ScopedArenaAllocator * local_allocator)573   explicit LoadStoreAnalysis(HGraph* graph,
574                              OptimizingCompilerStats* stats,
575                              ScopedArenaAllocator* local_allocator)
576       : graph_(graph), stats_(stats), heap_location_collector_(graph, local_allocator) {}
577 
GetHeapLocationCollector()578   const HeapLocationCollector& GetHeapLocationCollector() const {
579     return heap_location_collector_;
580   }
581 
582   bool Run();
583 
584  private:
585   HGraph* graph_;
586   OptimizingCompilerStats* stats_;
587   HeapLocationCollector heap_location_collector_;
588 
589   DISALLOW_COPY_AND_ASSIGN(LoadStoreAnalysis);
590 };
591 
592 }  // namespace art
593 
594 #endif  // ART_COMPILER_OPTIMIZING_LOAD_STORE_ANALYSIS_H_
595