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