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