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