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