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 "escape.h"
21 #include "nodes.h"
22 #include "optimization.h"
23 
24 namespace art {
25 
26 // A ReferenceInfo contains additional info about a reference such as
27 // whether it's a singleton, returned, etc.
28 class ReferenceInfo : public ArenaObject<kArenaAllocLSA> {
29  public:
ReferenceInfo(HInstruction * reference,size_t pos)30   ReferenceInfo(HInstruction* reference, size_t pos)
31       : reference_(reference),
32         position_(pos),
33         is_singleton_(true),
34         is_singleton_and_not_returned_(true),
35         is_singleton_and_not_deopt_visible_(true) {
36     CalculateEscape(reference_,
37                     nullptr,
38                     &is_singleton_,
39                     &is_singleton_and_not_returned_,
40                     &is_singleton_and_not_deopt_visible_);
41   }
42 
GetReference()43   HInstruction* GetReference() const {
44     return reference_;
45   }
46 
GetPosition()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).
IsSingleton()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.
IsSingletonAndRemovable()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.
IsSingletonAndNonRemovable()67   bool IsSingletonAndNonRemovable() const {
68     return is_singleton_ &&
69            (!is_singleton_and_not_returned_ || !is_singleton_and_not_deopt_visible_);
70   }
71 
72  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_;
82 
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.
88 class HeapLocation : public ArenaObject<kArenaAllocLSA> {
89  public:
90   static constexpr size_t kInvalidFieldOffset = -1;
91   // Default value for heap locations which are not vector data.
92   static constexpr size_t kScalar = 1;
93   // TODO: more fine-grained array types.
94   static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
95 
HeapLocation(ReferenceInfo * ref_info,size_t offset,HInstruction * index,size_t vector_length,int16_t declaring_class_def_index)96   HeapLocation(ReferenceInfo* ref_info,
97                size_t offset,
98                HInstruction* index,
99                size_t vector_length,
100                int16_t declaring_class_def_index)
101       : ref_info_(ref_info),
102         offset_(offset),
103         index_(index),
104         vector_length_(vector_length),
105         declaring_class_def_index_(declaring_class_def_index),
106         value_killed_by_loop_side_effects_(true),
107         has_aliased_locations_(false) {
108     DCHECK(ref_info != nullptr);
109     DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
110            (offset != kInvalidFieldOffset && index == nullptr));
111     if (ref_info->IsSingleton() && !IsArray()) {
112       // 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 
GetReferenceInfo()118   ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
GetOffset()119   size_t GetOffset() const { return offset_; }
GetIndex()120   HInstruction* GetIndex() const { return index_; }
GetVectorLength()121   size_t GetVectorLength() const { return vector_length_; }
122 
123   // Returns the definition of declaring class' dex index.
124   // It's kDeclaringClassDefIndexForArrays for an array element.
GetDeclaringClassDefIndex()125   int16_t GetDeclaringClassDefIndex() const {
126     return declaring_class_def_index_;
127   }
128 
IsArray()129   bool IsArray() const {
130     return index_ != nullptr;
131   }
132 
IsValueKilledByLoopSideEffects()133   bool IsValueKilledByLoopSideEffects() const {
134     return value_killed_by_loop_side_effects_;
135   }
136 
SetValueKilledByLoopSideEffects(bool val)137   void SetValueKilledByLoopSideEffects(bool val) {
138     value_killed_by_loop_side_effects_ = val;
139   }
140 
HasAliasedLocations()141   bool HasAliasedLocations() const {
142     return has_aliased_locations_;
143   }
144 
SetHasAliasedLocations(bool val)145   void SetHasAliasedLocations(bool val) {
146     has_aliased_locations_ = val;
147   }
148 
149  private:
150   // 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_;
170 
171   // 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 
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 : 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)188   explicit HeapLocationCollector(HGraph* graph)
189       : HGraphVisitor(graph),
190         ref_info_array_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
191         heap_locations_(graph->GetAllocator()->Adapter(kArenaAllocLSA)),
192         aliasing_matrix_(graph->GetAllocator(),
193                          kInitialAliasingMatrixBitVectorSize,
194                          true,
195                          kArenaAllocLSA),
196         has_heap_stores_(false),
197         has_volatile_(false),
198         has_monitor_operations_(false) {}
199 
CleanUp()200   void CleanUp() {
201     heap_locations_.clear();
202     ref_info_array_.clear();
203   }
204 
GetNumberOfHeapLocations()205   size_t GetNumberOfHeapLocations() const {
206     return heap_locations_.size();
207   }
208 
GetHeapLocation(size_t index)209   HeapLocation* GetHeapLocation(size_t index) const {
210     return heap_locations_[index];
211   }
212 
HuntForOriginalReference(HInstruction * ref)213   HInstruction* HuntForOriginalReference(HInstruction* ref) const {
214     // An original reference can be transformed by instructions like:
215     //   i0 NewArray
216     //   i1 HInstruction(i0)  <-- NullCheck, BoundType, IntermediateAddress.
217     //   i2 ArrayGet(i1, index)
218     DCHECK(ref != nullptr);
219     while (ref->IsNullCheck() || ref->IsBoundType() || ref->IsIntermediateAddress()) {
220       ref = ref->InputAt(0);
221     }
222     return ref;
223   }
224 
FindReferenceInfoOf(HInstruction * ref)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 
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->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 {
249     DCHECK(array != nullptr);
250     DCHECK(index != nullptr);
251     DCHECK_GE(vector_length, HeapLocation::kScalar);
252     return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
253                                  HeapLocation::kInvalidFieldOffset,
254                                  index,
255                                  vector_length,
256                                  HeapLocation::kDeclaringClassDefIndexForArrays);
257   }
258 
HasHeapStores()259   bool HasHeapStores() const {
260     return has_heap_stores_;
261   }
262 
HasVolatile()263   bool HasVolatile() const {
264     return has_volatile_;
265   }
266 
HasMonitorOps()267   bool HasMonitorOps() const {
268     return has_monitor_operations_;
269   }
270 
271   // Find and return the heap location index in heap_locations_.
272   // 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.
FindHeapLocationIndex(ReferenceInfo * ref_info,size_t offset,HInstruction * index,size_t vector_length,int16_t declaring_class_def_index)281   size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
282                                size_t offset,
283                                HInstruction* index,
284                                size_t vector_length,
285                                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 &&
291           loc->GetVectorLength() == vector_length &&
292           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.
MayAlias(size_t index1,size_t index2)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 
BuildAliasingMatrix()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.
MayAliasWithPreexistenceChecking(ReferenceInfo * ref_info1,ReferenceInfo * ref_info2)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 
CanReferencesAlias(ReferenceInfo * ref_info1,ReferenceInfo * ref_info2)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 
356   bool CanArrayElementsAlias(const HInstruction* idx1,
357                              const size_t vector_length1,
358                              const HInstruction* idx2,
359                              const size_t vector_length2) const;
360 
361   // `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.
AliasingMatrixPosition(size_t index1,size_t index2)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.
CheckedAliasingMatrixPosition(size_t index1,size_t index2,size_t position)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.
ComputeMayAlias(size_t index1,size_t index2)379   bool ComputeMayAlias(size_t index1, size_t index2) const {
380     DCHECK_NE(index1, index2);
381     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
385       // field and the other is an array data.
386       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     }
395     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)) {
401         return false;
402       }
403     }
404     loc1->SetHasAliasedLocations(true);
405     loc2->SetHasAliasedLocations(true);
406     return true;
407   }
408 
GetOrCreateReferenceInfo(HInstruction * instruction)409   ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
410     ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
411     if (ref_info == nullptr) {
412       size_t pos = ref_info_array_.size();
413       ref_info = new (GetGraph()->GetAllocator()) ReferenceInfo(instruction, pos);
414       ref_info_array_.push_back(ref_info);
415     }
416     return ref_info;
417   }
418 
CreateReferenceInfoForReferenceType(HInstruction * instruction)419   void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
420     if (instruction->GetType() != DataType::Type::kReference) {
421       return;
422     }
423     DCHECK(FindReferenceInfoOf(instruction) == nullptr);
424     GetOrCreateReferenceInfo(instruction);
425   }
426 
GetOrCreateHeapLocation(HInstruction * ref,size_t offset,HInstruction * index,size_t vector_length,int16_t declaring_class_def_index)427   HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
428                                         size_t offset,
429                                         HInstruction* index,
430                                         size_t vector_length,
431                                         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(
435         ref_info, offset, index, vector_length, declaring_class_def_index);
436     if (heap_location_idx == kHeapLocationNotFound) {
437       HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
438           HeapLocation(ref_info, offset, index, vector_length, declaring_class_def_index);
439       heap_locations_.push_back(heap_loc);
440       return heap_loc;
441     }
442     return heap_locations_[heap_location_idx];
443   }
444 
VisitFieldAccess(HInstruction * ref,const FieldInfo & field_info)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();
451     return GetOrCreateHeapLocation(ref,
452                                    offset,
453                                    nullptr,
454                                    HeapLocation::kScalar,
455                                    declaring_class_def_index);
456   }
457 
VisitArrayAccess(HInstruction * array,HInstruction * index,size_t vector_length)458   void VisitArrayAccess(HInstruction* array, HInstruction* index, size_t vector_length) {
459     GetOrCreateHeapLocation(array,
460                             HeapLocation::kInvalidFieldOffset,
461                             index,
462                             vector_length,
463                             HeapLocation::kDeclaringClassDefIndexForArrays);
464   }
465 
VisitInstanceFieldGet(HInstanceFieldGet * instruction)466   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
467     VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
468     CreateReferenceInfoForReferenceType(instruction);
469   }
470 
VisitInstanceFieldSet(HInstanceFieldSet * instruction)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 
VisitStaticFieldGet(HStaticFieldGet * instruction)497   void VisitStaticFieldGet(HStaticFieldGet* instruction) OVERRIDE {
498     VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
499     CreateReferenceInfoForReferenceType(instruction);
500   }
501 
VisitStaticFieldSet(HStaticFieldSet * instruction)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 
VisitArrayGet(HArrayGet * instruction)510   void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
511     HInstruction* array = instruction->InputAt(0);
512     HInstruction* index = instruction->InputAt(1);
513     VisitArrayAccess(array, index, HeapLocation::kScalar);
514     CreateReferenceInfoForReferenceType(instruction);
515   }
516 
VisitArraySet(HArraySet * instruction)517   void VisitArraySet(HArraySet* instruction) OVERRIDE {
518     HInstruction* array = instruction->InputAt(0);
519     HInstruction* index = instruction->InputAt(1);
520     VisitArrayAccess(array, index, HeapLocation::kScalar);
521     has_heap_stores_ = true;
522   }
523 
VisitVecLoad(HVecLoad * instruction)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 
VisitVecStore(HVecStore * instruction)531   void VisitVecStore(HVecStore* instruction) OVERRIDE {
532     HInstruction* array = instruction->InputAt(0);
533     HInstruction* index = instruction->InputAt(1);
534     VisitArrayAccess(array, index, instruction->GetVectorLength());
535     has_heap_stores_ = true;
536   }
537 
VisitInstruction(HInstruction * instruction)538   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.
547     CreateReferenceInfoForReferenceType(instruction);
548   }
549 
VisitMonitorOperation(HMonitorOperation * monitor ATTRIBUTE_UNUSED)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 
565 class LoadStoreAnalysis : public HOptimization {
566  public:
567   explicit LoadStoreAnalysis(HGraph* graph, const char* name = kLoadStoreAnalysisPassName)
HOptimization(graph,name)568     : HOptimization(graph, name),
569       heap_location_collector_(graph) {}
570 
GetHeapLocationCollector()571   const HeapLocationCollector& GetHeapLocationCollector() const {
572     return heap_location_collector_;
573   }
574 
575   void Run() OVERRIDE;
576 
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_
588