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