Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2015 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 #include "load_store_elimination.h"
     18 
     19 #include "escape.h"
     20 #include "side_effects_analysis.h"
     21 
     22 #include <iostream>
     23 
     24 namespace art {
     25 
     26 class ReferenceInfo;
     27 
     28 // A cap for the number of heap locations to prevent pathological time/space consumption.
     29 // The number of heap locations for most of the methods stays below this threshold.
     30 constexpr size_t kMaxNumberOfHeapLocations = 32;
     31 
     32 // A ReferenceInfo contains additional info about a reference such as
     33 // whether it's a singleton, returned, etc.
     34 class ReferenceInfo : public ArenaObject<kArenaAllocMisc> {
     35  public:
     36   ReferenceInfo(HInstruction* reference, size_t pos)
     37       : reference_(reference),
     38         position_(pos),
     39         is_singleton_(true),
     40         is_singleton_and_not_returned_(true),
     41         is_singleton_and_not_deopt_visible_(true),
     42         has_index_aliasing_(false) {
     43     CalculateEscape(reference_,
     44                     nullptr,
     45                     &is_singleton_,
     46                     &is_singleton_and_not_returned_,
     47                     &is_singleton_and_not_deopt_visible_);
     48   }
     49 
     50   HInstruction* GetReference() const {
     51     return reference_;
     52   }
     53 
     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).
     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.
     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.
     74   bool IsSingletonAndNonRemovable() const {
     75     return is_singleton_ &&
     76            (!is_singleton_and_not_returned_ || !is_singleton_and_not_deopt_visible_);
     77   }
     78 
     79   bool HasIndexAliasing() {
     80     return has_index_aliasing_;
     81   }
     82 
     83   void SetHasIndexAliasing(bool has_index_aliasing) {
     84     // Only allow setting to true.
     85     DCHECK(has_index_aliasing);
     86     has_index_aliasing_ = has_index_aliasing;
     87   }
     88 
     89  private:
     90   HInstruction* const reference_;
     91   const size_t position_;  // position in HeapLocationCollector's ref_info_array_.
     92 
     93   // Can only be referred to by a single name in the method.
     94   bool is_singleton_;
     95   // Is singleton and not returned to caller.
     96   bool is_singleton_and_not_returned_;
     97   // Is singleton and not used as an environment local of HDeoptimize.
     98   bool is_singleton_and_not_deopt_visible_;
     99   // Some heap locations with reference_ have array index aliasing,
    100   // e.g. arr[i] and arr[j] may be the same location.
    101   bool has_index_aliasing_;
    102 
    103   DISALLOW_COPY_AND_ASSIGN(ReferenceInfo);
    104 };
    105 
    106 // A heap location is a reference-offset/index pair that a value can be loaded from
    107 // or stored to.
    108 class HeapLocation : public ArenaObject<kArenaAllocMisc> {
    109  public:
    110   static constexpr size_t kInvalidFieldOffset = -1;
    111 
    112   // TODO: more fine-grained array types.
    113   static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
    114 
    115   HeapLocation(ReferenceInfo* ref_info,
    116                size_t offset,
    117                HInstruction* index,
    118                int16_t declaring_class_def_index)
    119       : ref_info_(ref_info),
    120         offset_(offset),
    121         index_(index),
    122         declaring_class_def_index_(declaring_class_def_index),
    123         value_killed_by_loop_side_effects_(true) {
    124     DCHECK(ref_info != nullptr);
    125     DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
    126            (offset != kInvalidFieldOffset && index == nullptr));
    127     if (ref_info->IsSingleton() && !IsArrayElement()) {
    128       // Assume this location's value cannot be killed by loop side effects
    129       // until proven otherwise.
    130       value_killed_by_loop_side_effects_ = false;
    131     }
    132   }
    133 
    134   ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
    135   size_t GetOffset() const { return offset_; }
    136   HInstruction* GetIndex() const { return index_; }
    137 
    138   // Returns the definition of declaring class' dex index.
    139   // It's kDeclaringClassDefIndexForArrays for an array element.
    140   int16_t GetDeclaringClassDefIndex() const {
    141     return declaring_class_def_index_;
    142   }
    143 
    144   bool IsArrayElement() const {
    145     return index_ != nullptr;
    146   }
    147 
    148   bool IsValueKilledByLoopSideEffects() const {
    149     return value_killed_by_loop_side_effects_;
    150   }
    151 
    152   void SetValueKilledByLoopSideEffects(bool val) {
    153     value_killed_by_loop_side_effects_ = val;
    154   }
    155 
    156  private:
    157   ReferenceInfo* const ref_info_;      // reference for instance/static field or array access.
    158   const size_t offset_;                // offset of static/instance field.
    159   HInstruction* const index_;          // index of an array element.
    160   const int16_t declaring_class_def_index_;  // declaring class's def's dex index.
    161   bool value_killed_by_loop_side_effects_;   // value of this location may be killed by loop
    162                                              // side effects because this location is stored
    163                                              // into inside a loop. This gives
    164                                              // better info on whether a singleton's location
    165                                              // value may be killed by loop side effects.
    166 
    167   DISALLOW_COPY_AND_ASSIGN(HeapLocation);
    168 };
    169 
    170 static HInstruction* HuntForOriginalReference(HInstruction* ref) {
    171   DCHECK(ref != nullptr);
    172   while (ref->IsNullCheck() || ref->IsBoundType()) {
    173     ref = ref->InputAt(0);
    174   }
    175   return ref;
    176 }
    177 
    178 // A HeapLocationCollector collects all relevant heap locations and keeps
    179 // an aliasing matrix for all locations.
    180 class HeapLocationCollector : public HGraphVisitor {
    181  public:
    182   static constexpr size_t kHeapLocationNotFound = -1;
    183   // Start with a single uint32_t word. That's enough bits for pair-wise
    184   // aliasing matrix of 8 heap locations.
    185   static constexpr uint32_t kInitialAliasingMatrixBitVectorSize = 32;
    186 
    187   explicit HeapLocationCollector(HGraph* graph)
    188       : HGraphVisitor(graph),
    189         ref_info_array_(graph->GetArena()->Adapter(kArenaAllocLSE)),
    190         heap_locations_(graph->GetArena()->Adapter(kArenaAllocLSE)),
    191         aliasing_matrix_(graph->GetArena(),
    192                          kInitialAliasingMatrixBitVectorSize,
    193                          true,
    194                          kArenaAllocLSE),
    195         has_heap_stores_(false),
    196         has_volatile_(false),
    197         has_monitor_operations_(false) {}
    198 
    199   size_t GetNumberOfHeapLocations() const {
    200     return heap_locations_.size();
    201   }
    202 
    203   HeapLocation* GetHeapLocation(size_t index) const {
    204     return heap_locations_[index];
    205   }
    206 
    207   ReferenceInfo* FindReferenceInfoOf(HInstruction* ref) const {
    208     for (size_t i = 0; i < ref_info_array_.size(); i++) {
    209       ReferenceInfo* ref_info = ref_info_array_[i];
    210       if (ref_info->GetReference() == ref) {
    211         DCHECK_EQ(i, ref_info->GetPosition());
    212         return ref_info;
    213       }
    214     }
    215     return nullptr;
    216   }
    217 
    218   bool HasHeapStores() const {
    219     return has_heap_stores_;
    220   }
    221 
    222   bool HasVolatile() const {
    223     return has_volatile_;
    224   }
    225 
    226   bool HasMonitorOps() const {
    227     return has_monitor_operations_;
    228   }
    229 
    230   // Find and return the heap location index in heap_locations_.
    231   size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
    232                                size_t offset,
    233                                HInstruction* index,
    234                                int16_t declaring_class_def_index) const {
    235     for (size_t i = 0; i < heap_locations_.size(); i++) {
    236       HeapLocation* loc = heap_locations_[i];
    237       if (loc->GetReferenceInfo() == ref_info &&
    238           loc->GetOffset() == offset &&
    239           loc->GetIndex() == index &&
    240           loc->GetDeclaringClassDefIndex() == declaring_class_def_index) {
    241         return i;
    242       }
    243     }
    244     return kHeapLocationNotFound;
    245   }
    246 
    247   // Returns true if heap_locations_[index1] and heap_locations_[index2] may alias.
    248   bool MayAlias(size_t index1, size_t index2) const {
    249     if (index1 < index2) {
    250       return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index1, index2));
    251     } else if (index1 > index2) {
    252       return aliasing_matrix_.IsBitSet(AliasingMatrixPosition(index2, index1));
    253     } else {
    254       DCHECK(false) << "index1 and index2 are expected to be different";
    255       return true;
    256     }
    257   }
    258 
    259   void BuildAliasingMatrix() {
    260     const size_t number_of_locations = heap_locations_.size();
    261     if (number_of_locations == 0) {
    262       return;
    263     }
    264     size_t pos = 0;
    265     // Compute aliasing info between every pair of different heap locations.
    266     // Save the result in a matrix represented as a BitVector.
    267     for (size_t i = 0; i < number_of_locations - 1; i++) {
    268       for (size_t j = i + 1; j < number_of_locations; j++) {
    269         if (ComputeMayAlias(i, j)) {
    270           aliasing_matrix_.SetBit(CheckedAliasingMatrixPosition(i, j, pos));
    271         }
    272         pos++;
    273       }
    274     }
    275   }
    276 
    277  private:
    278   // An allocation cannot alias with a name which already exists at the point
    279   // of the allocation, such as a parameter or a load happening before the allocation.
    280   bool MayAliasWithPreexistenceChecking(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
    281     if (ref_info1->GetReference()->IsNewInstance() || ref_info1->GetReference()->IsNewArray()) {
    282       // Any reference that can alias with the allocation must appear after it in the block/in
    283       // the block's successors. In reverse post order, those instructions will be visited after
    284       // the allocation.
    285       return ref_info2->GetPosition() >= ref_info1->GetPosition();
    286     }
    287     return true;
    288   }
    289 
    290   bool CanReferencesAlias(ReferenceInfo* ref_info1, ReferenceInfo* ref_info2) const {
    291     if (ref_info1 == ref_info2) {
    292       return true;
    293     } else if (ref_info1->IsSingleton()) {
    294       return false;
    295     } else if (ref_info2->IsSingleton()) {
    296       return false;
    297     } else if (!MayAliasWithPreexistenceChecking(ref_info1, ref_info2) ||
    298         !MayAliasWithPreexistenceChecking(ref_info2, ref_info1)) {
    299       return false;
    300     }
    301     return true;
    302   }
    303 
    304   // `index1` and `index2` are indices in the array of collected heap locations.
    305   // Returns the position in the bit vector that tracks whether the two heap
    306   // locations may alias.
    307   size_t AliasingMatrixPosition(size_t index1, size_t index2) const {
    308     DCHECK(index2 > index1);
    309     const size_t number_of_locations = heap_locations_.size();
    310     // It's (num_of_locations - 1) + ... + (num_of_locations - index1) + (index2 - index1 - 1).
    311     return (number_of_locations * index1 - (1 + index1) * index1 / 2 + (index2 - index1 - 1));
    312   }
    313 
    314   // An additional position is passed in to make sure the calculated position is correct.
    315   size_t CheckedAliasingMatrixPosition(size_t index1, size_t index2, size_t position) {
    316     size_t calculated_position = AliasingMatrixPosition(index1, index2);
    317     DCHECK_EQ(calculated_position, position);
    318     return calculated_position;
    319   }
    320 
    321   // Compute if two locations may alias to each other.
    322   bool ComputeMayAlias(size_t index1, size_t index2) const {
    323     HeapLocation* loc1 = heap_locations_[index1];
    324     HeapLocation* loc2 = heap_locations_[index2];
    325     if (loc1->GetOffset() != loc2->GetOffset()) {
    326       // Either two different instance fields, or one is an instance
    327       // field and the other is an array element.
    328       return false;
    329     }
    330     if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
    331       // Different types.
    332       return false;
    333     }
    334     if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
    335       return false;
    336     }
    337     if (loc1->IsArrayElement() && loc2->IsArrayElement()) {
    338       HInstruction* array_index1 = loc1->GetIndex();
    339       HInstruction* array_index2 = loc2->GetIndex();
    340       DCHECK(array_index1 != nullptr);
    341       DCHECK(array_index2 != nullptr);
    342       if (array_index1->IsIntConstant() &&
    343           array_index2->IsIntConstant() &&
    344           array_index1->AsIntConstant()->GetValue() != array_index2->AsIntConstant()->GetValue()) {
    345         // Different constant indices do not alias.
    346         return false;
    347       }
    348       ReferenceInfo* ref_info = loc1->GetReferenceInfo();
    349       ref_info->SetHasIndexAliasing(true);
    350     }
    351     return true;
    352   }
    353 
    354   ReferenceInfo* GetOrCreateReferenceInfo(HInstruction* instruction) {
    355     ReferenceInfo* ref_info = FindReferenceInfoOf(instruction);
    356     if (ref_info == nullptr) {
    357       size_t pos = ref_info_array_.size();
    358       ref_info = new (GetGraph()->GetArena()) ReferenceInfo(instruction, pos);
    359       ref_info_array_.push_back(ref_info);
    360     }
    361     return ref_info;
    362   }
    363 
    364   void CreateReferenceInfoForReferenceType(HInstruction* instruction) {
    365     if (instruction->GetType() != Primitive::kPrimNot) {
    366       return;
    367     }
    368     DCHECK(FindReferenceInfoOf(instruction) == nullptr);
    369     GetOrCreateReferenceInfo(instruction);
    370   }
    371 
    372   HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
    373                                         size_t offset,
    374                                         HInstruction* index,
    375                                         int16_t declaring_class_def_index) {
    376     HInstruction* original_ref = HuntForOriginalReference(ref);
    377     ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
    378     size_t heap_location_idx = FindHeapLocationIndex(
    379         ref_info, offset, index, declaring_class_def_index);
    380     if (heap_location_idx == kHeapLocationNotFound) {
    381       HeapLocation* heap_loc = new (GetGraph()->GetArena())
    382           HeapLocation(ref_info, offset, index, declaring_class_def_index);
    383       heap_locations_.push_back(heap_loc);
    384       return heap_loc;
    385     }
    386     return heap_locations_[heap_location_idx];
    387   }
    388 
    389   HeapLocation* VisitFieldAccess(HInstruction* ref, const FieldInfo& field_info) {
    390     if (field_info.IsVolatile()) {
    391       has_volatile_ = true;
    392     }
    393     const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
    394     const size_t offset = field_info.GetFieldOffset().SizeValue();
    395     return GetOrCreateHeapLocation(ref, offset, nullptr, declaring_class_def_index);
    396   }
    397 
    398   void VisitArrayAccess(HInstruction* array, HInstruction* index) {
    399     GetOrCreateHeapLocation(array, HeapLocation::kInvalidFieldOffset,
    400         index, HeapLocation::kDeclaringClassDefIndexForArrays);
    401   }
    402 
    403   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
    404     VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
    405     CreateReferenceInfoForReferenceType(instruction);
    406   }
    407 
    408   void VisitInstanceFieldSet(HInstanceFieldSet* instruction) OVERRIDE {
    409     HeapLocation* location = VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
    410     has_heap_stores_ = true;
    411     if (location->GetReferenceInfo()->IsSingleton()) {
    412       // A singleton's location value may be killed by loop side effects if it's
    413       // defined before that loop, and it's stored into inside that loop.
    414       HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
    415       if (loop_info != nullptr) {
    416         HInstruction* ref = location->GetReferenceInfo()->GetReference();
    417         DCHECK(ref->IsNewInstance());
    418         if (loop_info->IsDefinedOutOfTheLoop(ref)) {
    419           // ref's location value may be killed by this loop's side effects.
    420           location->SetValueKilledByLoopSideEffects(true);
    421         } else {
    422           // ref is defined inside this loop so this loop's side effects cannot
    423           // kill its location value at the loop header since ref/its location doesn't
    424           // exist yet at the loop header.
    425         }
    426       }
    427     } else {
    428       // For non-singletons, value_killed_by_loop_side_effects_ is inited to
    429       // true.
    430       DCHECK_EQ(location->IsValueKilledByLoopSideEffects(), true);
    431     }
    432   }
    433 
    434   void VisitStaticFieldGet(HStaticFieldGet* instruction) OVERRIDE {
    435     VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
    436     CreateReferenceInfoForReferenceType(instruction);
    437   }
    438 
    439   void VisitStaticFieldSet(HStaticFieldSet* instruction) OVERRIDE {
    440     VisitFieldAccess(instruction->InputAt(0), instruction->GetFieldInfo());
    441     has_heap_stores_ = true;
    442   }
    443 
    444   // We intentionally don't collect HUnresolvedInstanceField/HUnresolvedStaticField accesses
    445   // since we cannot accurately track the fields.
    446 
    447   void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
    448     VisitArrayAccess(instruction->InputAt(0), instruction->InputAt(1));
    449     CreateReferenceInfoForReferenceType(instruction);
    450   }
    451 
    452   void VisitArraySet(HArraySet* instruction) OVERRIDE {
    453     VisitArrayAccess(instruction->InputAt(0), instruction->InputAt(1));
    454     has_heap_stores_ = true;
    455   }
    456 
    457   void VisitNewInstance(HNewInstance* new_instance) OVERRIDE {
    458     // Any references appearing in the ref_info_array_ so far cannot alias with new_instance.
    459     CreateReferenceInfoForReferenceType(new_instance);
    460   }
    461 
    462   void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* instruction) OVERRIDE {
    463     CreateReferenceInfoForReferenceType(instruction);
    464   }
    465 
    466   void VisitInvokeVirtual(HInvokeVirtual* instruction) OVERRIDE {
    467     CreateReferenceInfoForReferenceType(instruction);
    468   }
    469 
    470   void VisitInvokeInterface(HInvokeInterface* instruction) OVERRIDE {
    471     CreateReferenceInfoForReferenceType(instruction);
    472   }
    473 
    474   void VisitParameterValue(HParameterValue* instruction) OVERRIDE {
    475     CreateReferenceInfoForReferenceType(instruction);
    476   }
    477 
    478   void VisitSelect(HSelect* instruction) OVERRIDE {
    479     CreateReferenceInfoForReferenceType(instruction);
    480   }
    481 
    482   void VisitMonitorOperation(HMonitorOperation* monitor ATTRIBUTE_UNUSED) OVERRIDE {
    483     has_monitor_operations_ = true;
    484   }
    485 
    486   ArenaVector<ReferenceInfo*> ref_info_array_;   // All references used for heap accesses.
    487   ArenaVector<HeapLocation*> heap_locations_;    // All heap locations.
    488   ArenaBitVector aliasing_matrix_;    // aliasing info between each pair of locations.
    489   bool has_heap_stores_;    // If there is no heap stores, LSE acts as GVN with better
    490                             // alias analysis and won't be as effective.
    491   bool has_volatile_;       // If there are volatile field accesses.
    492   bool has_monitor_operations_;    // If there are monitor operations.
    493 
    494   DISALLOW_COPY_AND_ASSIGN(HeapLocationCollector);
    495 };
    496 
    497 // An unknown heap value. Loads with such a value in the heap location cannot be eliminated.
    498 // A heap location can be set to kUnknownHeapValue when:
    499 // - initially set a value.
    500 // - killed due to aliasing, merging, invocation, or loop side effects.
    501 static HInstruction* const kUnknownHeapValue =
    502     reinterpret_cast<HInstruction*>(static_cast<uintptr_t>(-1));
    503 
    504 // Default heap value after an allocation.
    505 // A heap location can be set to that value right after an allocation.
    506 static HInstruction* const kDefaultHeapValue =
    507     reinterpret_cast<HInstruction*>(static_cast<uintptr_t>(-2));
    508 
    509 class LSEVisitor : public HGraphVisitor {
    510  public:
    511   LSEVisitor(HGraph* graph,
    512              const HeapLocationCollector& heap_locations_collector,
    513              const SideEffectsAnalysis& side_effects)
    514       : HGraphVisitor(graph),
    515         heap_location_collector_(heap_locations_collector),
    516         side_effects_(side_effects),
    517         heap_values_for_(graph->GetBlocks().size(),
    518                          ArenaVector<HInstruction*>(heap_locations_collector.
    519                                                         GetNumberOfHeapLocations(),
    520                                                     kUnknownHeapValue,
    521                                                     graph->GetArena()->Adapter(kArenaAllocLSE)),
    522                          graph->GetArena()->Adapter(kArenaAllocLSE)),
    523         removed_loads_(graph->GetArena()->Adapter(kArenaAllocLSE)),
    524         substitute_instructions_for_loads_(graph->GetArena()->Adapter(kArenaAllocLSE)),
    525         possibly_removed_stores_(graph->GetArena()->Adapter(kArenaAllocLSE)),
    526         singleton_new_instances_(graph->GetArena()->Adapter(kArenaAllocLSE)),
    527         singleton_new_arrays_(graph->GetArena()->Adapter(kArenaAllocLSE)) {
    528   }
    529 
    530   void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
    531     // Populate the heap_values array for this block.
    532     // TODO: try to reuse the heap_values array from one predecessor if possible.
    533     if (block->IsLoopHeader()) {
    534       HandleLoopSideEffects(block);
    535     } else {
    536       MergePredecessorValues(block);
    537     }
    538     HGraphVisitor::VisitBasicBlock(block);
    539   }
    540 
    541   // Remove recorded instructions that should be eliminated.
    542   void RemoveInstructions() {
    543     size_t size = removed_loads_.size();
    544     DCHECK_EQ(size, substitute_instructions_for_loads_.size());
    545     for (size_t i = 0; i < size; i++) {
    546       HInstruction* load = removed_loads_[i];
    547       DCHECK(load != nullptr);
    548       DCHECK(load->IsInstanceFieldGet() ||
    549              load->IsStaticFieldGet() ||
    550              load->IsArrayGet());
    551       HInstruction* substitute = substitute_instructions_for_loads_[i];
    552       DCHECK(substitute != nullptr);
    553       // Keep tracing substitute till one that's not removed.
    554       HInstruction* sub_sub = FindSubstitute(substitute);
    555       while (sub_sub != substitute) {
    556         substitute = sub_sub;
    557         sub_sub = FindSubstitute(substitute);
    558       }
    559       load->ReplaceWith(substitute);
    560       load->GetBlock()->RemoveInstruction(load);
    561     }
    562 
    563     // At this point, stores in possibly_removed_stores_ can be safely removed.
    564     for (HInstruction* store : possibly_removed_stores_) {
    565       DCHECK(store->IsInstanceFieldSet() || store->IsStaticFieldSet() || store->IsArraySet());
    566       store->GetBlock()->RemoveInstruction(store);
    567     }
    568 
    569     // Eliminate allocations that are not used.
    570     for (HInstruction* new_instance : singleton_new_instances_) {
    571       if (!new_instance->HasNonEnvironmentUses()) {
    572         new_instance->RemoveEnvironmentUsers();
    573         new_instance->GetBlock()->RemoveInstruction(new_instance);
    574       }
    575     }
    576     for (HInstruction* new_array : singleton_new_arrays_) {
    577       if (!new_array->HasNonEnvironmentUses()) {
    578         new_array->RemoveEnvironmentUsers();
    579         new_array->GetBlock()->RemoveInstruction(new_array);
    580       }
    581     }
    582   }
    583 
    584  private:
    585   // If heap_values[index] is an instance field store, need to keep the store.
    586   // This is necessary if a heap value is killed due to merging, or loop side
    587   // effects (which is essentially merging also), since a load later from the
    588   // location won't be eliminated.
    589   void KeepIfIsStore(HInstruction* heap_value) {
    590     if (heap_value == kDefaultHeapValue ||
    591         heap_value == kUnknownHeapValue ||
    592         !(heap_value->IsInstanceFieldSet() || heap_value->IsArraySet())) {
    593       return;
    594     }
    595     auto idx = std::find(possibly_removed_stores_.begin(),
    596         possibly_removed_stores_.end(), heap_value);
    597     if (idx != possibly_removed_stores_.end()) {
    598       // Make sure the store is kept.
    599       possibly_removed_stores_.erase(idx);
    600     }
    601   }
    602 
    603   void HandleLoopSideEffects(HBasicBlock* block) {
    604     DCHECK(block->IsLoopHeader());
    605     int block_id = block->GetBlockId();
    606     ArenaVector<HInstruction*>& heap_values = heap_values_for_[block_id];
    607 
    608     // Don't eliminate loads in irreducible loops. This is safe for singletons, because
    609     // they are always used by the non-eliminated loop-phi.
    610     if (block->GetLoopInformation()->IsIrreducible()) {
    611       if (kIsDebugBuild) {
    612         for (size_t i = 0; i < heap_values.size(); i++) {
    613           DCHECK_EQ(heap_values[i], kUnknownHeapValue);
    614         }
    615       }
    616       return;
    617     }
    618 
    619     HBasicBlock* pre_header = block->GetLoopInformation()->GetPreHeader();
    620     ArenaVector<HInstruction*>& pre_header_heap_values =
    621         heap_values_for_[pre_header->GetBlockId()];
    622 
    623     // Inherit the values from pre-header.
    624     for (size_t i = 0; i < heap_values.size(); i++) {
    625       heap_values[i] = pre_header_heap_values[i];
    626     }
    627 
    628     // We do a single pass in reverse post order. For loops, use the side effects as a hint
    629     // to see if the heap values should be killed.
    630     if (side_effects_.GetLoopEffects(block).DoesAnyWrite()) {
    631       for (size_t i = 0; i < heap_values.size(); i++) {
    632         HeapLocation* location = heap_location_collector_.GetHeapLocation(i);
    633         ReferenceInfo* ref_info = location->GetReferenceInfo();
    634         if (ref_info->IsSingletonAndRemovable() &&
    635             !location->IsValueKilledByLoopSideEffects()) {
    636           // A removable singleton's field that's not stored into inside a loop is
    637           // invariant throughout the loop. Nothing to do.
    638           DCHECK(ref_info->IsSingletonAndRemovable());
    639         } else {
    640           // heap value is killed by loop side effects (stored into directly, or
    641           // due to aliasing). Or the heap value may be needed after method return
    642           // or deoptimization.
    643           KeepIfIsStore(pre_header_heap_values[i]);
    644           heap_values[i] = kUnknownHeapValue;
    645         }
    646       }
    647     }
    648   }
    649 
    650   void MergePredecessorValues(HBasicBlock* block) {
    651     const ArenaVector<HBasicBlock*>& predecessors = block->GetPredecessors();
    652     if (predecessors.size() == 0) {
    653       return;
    654     }
    655 
    656     ArenaVector<HInstruction*>& heap_values = heap_values_for_[block->GetBlockId()];
    657     for (size_t i = 0; i < heap_values.size(); i++) {
    658       HInstruction* merged_value = nullptr;
    659       // Whether merged_value is a result that's merged from all predecessors.
    660       bool from_all_predecessors = true;
    661       ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
    662       HInstruction* singleton_ref = nullptr;
    663       if (ref_info->IsSingleton()) {
    664         // We do more analysis of liveness when merging heap values for such
    665         // cases since stores into such references may potentially be eliminated.
    666         singleton_ref = ref_info->GetReference();
    667       }
    668 
    669       for (HBasicBlock* predecessor : predecessors) {
    670         HInstruction* pred_value = heap_values_for_[predecessor->GetBlockId()][i];
    671         if ((singleton_ref != nullptr) &&
    672             !singleton_ref->GetBlock()->Dominates(predecessor)) {
    673           // singleton_ref is not live in this predecessor. Skip this predecessor since
    674           // it does not really have the location.
    675           DCHECK_EQ(pred_value, kUnknownHeapValue);
    676           from_all_predecessors = false;
    677           continue;
    678         }
    679         if (merged_value == nullptr) {
    680           // First seen heap value.
    681           merged_value = pred_value;
    682         } else if (pred_value != merged_value) {
    683           // There are conflicting values.
    684           merged_value = kUnknownHeapValue;
    685           break;
    686         }
    687       }
    688 
    689       if (merged_value == kUnknownHeapValue || ref_info->IsSingletonAndNonRemovable()) {
    690         // There are conflicting heap values from different predecessors,
    691         // or the heap value may be needed after method return or deoptimization.
    692         // Keep the last store in each predecessor since future loads cannot be eliminated.
    693         for (HBasicBlock* predecessor : predecessors) {
    694           ArenaVector<HInstruction*>& pred_values = heap_values_for_[predecessor->GetBlockId()];
    695           KeepIfIsStore(pred_values[i]);
    696         }
    697       }
    698 
    699       if ((merged_value == nullptr) || !from_all_predecessors) {
    700         DCHECK(singleton_ref != nullptr);
    701         DCHECK((singleton_ref->GetBlock() == block) ||
    702                !singleton_ref->GetBlock()->Dominates(block));
    703         // singleton_ref is not defined before block or defined only in some of its
    704         // predecessors, so block doesn't really have the location at its entry.
    705         heap_values[i] = kUnknownHeapValue;
    706       } else {
    707         heap_values[i] = merged_value;
    708       }
    709     }
    710   }
    711 
    712   // `instruction` is being removed. Try to see if the null check on it
    713   // can be removed. This can happen if the same value is set in two branches
    714   // but not in dominators. Such as:
    715   //   int[] a = foo();
    716   //   if () {
    717   //     a[0] = 2;
    718   //   } else {
    719   //     a[0] = 2;
    720   //   }
    721   //   // a[0] can now be replaced with constant 2, and the null check on it can be removed.
    722   void TryRemovingNullCheck(HInstruction* instruction) {
    723     HInstruction* prev = instruction->GetPrevious();
    724     if ((prev != nullptr) && prev->IsNullCheck() && (prev == instruction->InputAt(0))) {
    725       // Previous instruction is a null check for this instruction. Remove the null check.
    726       prev->ReplaceWith(prev->InputAt(0));
    727       prev->GetBlock()->RemoveInstruction(prev);
    728     }
    729   }
    730 
    731   HInstruction* GetDefaultValue(Primitive::Type type) {
    732     switch (type) {
    733       case Primitive::kPrimNot:
    734         return GetGraph()->GetNullConstant();
    735       case Primitive::kPrimBoolean:
    736       case Primitive::kPrimByte:
    737       case Primitive::kPrimChar:
    738       case Primitive::kPrimShort:
    739       case Primitive::kPrimInt:
    740         return GetGraph()->GetIntConstant(0);
    741       case Primitive::kPrimLong:
    742         return GetGraph()->GetLongConstant(0);
    743       case Primitive::kPrimFloat:
    744         return GetGraph()->GetFloatConstant(0);
    745       case Primitive::kPrimDouble:
    746         return GetGraph()->GetDoubleConstant(0);
    747       default:
    748         UNREACHABLE();
    749     }
    750   }
    751 
    752   void VisitGetLocation(HInstruction* instruction,
    753                         HInstruction* ref,
    754                         size_t offset,
    755                         HInstruction* index,
    756                         int16_t declaring_class_def_index) {
    757     HInstruction* original_ref = HuntForOriginalReference(ref);
    758     ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(original_ref);
    759     size_t idx = heap_location_collector_.FindHeapLocationIndex(
    760         ref_info, offset, index, declaring_class_def_index);
    761     DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
    762     ArenaVector<HInstruction*>& heap_values =
    763         heap_values_for_[instruction->GetBlock()->GetBlockId()];
    764     HInstruction* heap_value = heap_values[idx];
    765     if (heap_value == kDefaultHeapValue) {
    766       HInstruction* constant = GetDefaultValue(instruction->GetType());
    767       removed_loads_.push_back(instruction);
    768       substitute_instructions_for_loads_.push_back(constant);
    769       heap_values[idx] = constant;
    770       return;
    771     }
    772     if (heap_value != kUnknownHeapValue) {
    773       if (heap_value->IsInstanceFieldSet() || heap_value->IsArraySet()) {
    774         HInstruction* store = heap_value;
    775         // This load must be from a singleton since it's from the same
    776         // field/element that a "removed" store puts the value. That store
    777         // must be to a singleton's field/element.
    778         DCHECK(ref_info->IsSingleton());
    779         // Get the real heap value of the store.
    780         heap_value = heap_value->IsInstanceFieldSet() ? store->InputAt(1) : store->InputAt(2);
    781       }
    782     }
    783     if (heap_value == kUnknownHeapValue) {
    784       // Load isn't eliminated. Put the load as the value into the HeapLocation.
    785       // This acts like GVN but with better aliasing analysis.
    786       heap_values[idx] = instruction;
    787     } else {
    788       if (Primitive::PrimitiveKind(heap_value->GetType())
    789               != Primitive::PrimitiveKind(instruction->GetType())) {
    790         // The only situation where the same heap location has different type is when
    791         // we do an array get on an instruction that originates from the null constant
    792         // (the null could be behind a field access, an array access, a null check or
    793         // a bound type).
    794         // In order to stay properly typed on primitive types, we do not eliminate
    795         // the array gets.
    796         if (kIsDebugBuild) {
    797           DCHECK(heap_value->IsArrayGet()) << heap_value->DebugName();
    798           DCHECK(instruction->IsArrayGet()) << instruction->DebugName();
    799         }
    800         return;
    801       }
    802       removed_loads_.push_back(instruction);
    803       substitute_instructions_for_loads_.push_back(heap_value);
    804       TryRemovingNullCheck(instruction);
    805     }
    806   }
    807 
    808   bool Equal(HInstruction* heap_value, HInstruction* value) {
    809     if (heap_value == value) {
    810       return true;
    811     }
    812     if (heap_value == kDefaultHeapValue && GetDefaultValue(value->GetType()) == value) {
    813       return true;
    814     }
    815     return false;
    816   }
    817 
    818   void VisitSetLocation(HInstruction* instruction,
    819                         HInstruction* ref,
    820                         size_t offset,
    821                         HInstruction* index,
    822                         int16_t declaring_class_def_index,
    823                         HInstruction* value) {
    824     HInstruction* original_ref = HuntForOriginalReference(ref);
    825     ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(original_ref);
    826     size_t idx = heap_location_collector_.FindHeapLocationIndex(
    827         ref_info, offset, index, declaring_class_def_index);
    828     DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
    829     ArenaVector<HInstruction*>& heap_values =
    830         heap_values_for_[instruction->GetBlock()->GetBlockId()];
    831     HInstruction* heap_value = heap_values[idx];
    832     bool same_value = false;
    833     bool possibly_redundant = false;
    834     if (Equal(heap_value, value)) {
    835       // Store into the heap location with the same value.
    836       same_value = true;
    837     } else if (index != nullptr && ref_info->HasIndexAliasing()) {
    838       // For array element, don't eliminate stores if the index can be aliased.
    839     } else if (ref_info->IsSingleton()) {
    840       // Store into a field of a singleton. The value cannot be killed due to
    841       // aliasing/invocation. It can be redundant since future loads can
    842       // directly get the value set by this instruction. The value can still be killed due to
    843       // merging or loop side effects. Stores whose values are killed due to merging/loop side
    844       // effects later will be removed from possibly_removed_stores_ when that is detected.
    845       // Stores whose values may be needed after method return or deoptimization
    846       // are also removed from possibly_removed_stores_ when that is detected.
    847       possibly_redundant = true;
    848       HNewInstance* new_instance = ref_info->GetReference()->AsNewInstance();
    849       if (new_instance != nullptr && new_instance->IsFinalizable()) {
    850         // Finalizable objects escape globally. Need to keep the store.
    851         possibly_redundant = false;
    852       } else {
    853         HLoopInformation* loop_info = instruction->GetBlock()->GetLoopInformation();
    854         if (loop_info != nullptr) {
    855           // instruction is a store in the loop so the loop must does write.
    856           DCHECK(side_effects_.GetLoopEffects(loop_info->GetHeader()).DoesAnyWrite());
    857 
    858           if (loop_info->IsDefinedOutOfTheLoop(original_ref)) {
    859             DCHECK(original_ref->GetBlock()->Dominates(loop_info->GetPreHeader()));
    860             // Keep the store since its value may be needed at the loop header.
    861             possibly_redundant = false;
    862           } else {
    863             // The singleton is created inside the loop. Value stored to it isn't needed at
    864             // the loop header. This is true for outer loops also.
    865           }
    866         }
    867       }
    868     }
    869     if (same_value || possibly_redundant) {
    870       possibly_removed_stores_.push_back(instruction);
    871     }
    872 
    873     if (!same_value) {
    874       if (possibly_redundant) {
    875         DCHECK(instruction->IsInstanceFieldSet() || instruction->IsArraySet());
    876         // Put the store as the heap value. If the value is loaded from heap
    877         // by a load later, this store isn't really redundant.
    878         heap_values[idx] = instruction;
    879       } else {
    880         heap_values[idx] = value;
    881       }
    882     }
    883     // This store may kill values in other heap locations due to aliasing.
    884     for (size_t i = 0; i < heap_values.size(); i++) {
    885       if (i == idx) {
    886         continue;
    887       }
    888       if (heap_values[i] == value) {
    889         // Same value should be kept even if aliasing happens.
    890         continue;
    891       }
    892       if (heap_values[i] == kUnknownHeapValue) {
    893         // Value is already unknown, no need for aliasing check.
    894         continue;
    895       }
    896       if (heap_location_collector_.MayAlias(i, idx)) {
    897         // Kill heap locations that may alias.
    898         heap_values[i] = kUnknownHeapValue;
    899       }
    900     }
    901   }
    902 
    903   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
    904     HInstruction* obj = instruction->InputAt(0);
    905     size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
    906     int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
    907     VisitGetLocation(instruction, obj, offset, nullptr, declaring_class_def_index);
    908   }
    909 
    910   void VisitInstanceFieldSet(HInstanceFieldSet* instruction) OVERRIDE {
    911     HInstruction* obj = instruction->InputAt(0);
    912     size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
    913     int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
    914     HInstruction* value = instruction->InputAt(1);
    915     VisitSetLocation(instruction, obj, offset, nullptr, declaring_class_def_index, value);
    916   }
    917 
    918   void VisitStaticFieldGet(HStaticFieldGet* instruction) OVERRIDE {
    919     HInstruction* cls = instruction->InputAt(0);
    920     size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
    921     int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
    922     VisitGetLocation(instruction, cls, offset, nullptr, declaring_class_def_index);
    923   }
    924 
    925   void VisitStaticFieldSet(HStaticFieldSet* instruction) OVERRIDE {
    926     HInstruction* cls = instruction->InputAt(0);
    927     size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
    928     int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
    929     HInstruction* value = instruction->InputAt(1);
    930     VisitSetLocation(instruction, cls, offset, nullptr, declaring_class_def_index, value);
    931   }
    932 
    933   void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
    934     HInstruction* array = instruction->InputAt(0);
    935     HInstruction* index = instruction->InputAt(1);
    936     VisitGetLocation(instruction,
    937                      array,
    938                      HeapLocation::kInvalidFieldOffset,
    939                      index,
    940                      HeapLocation::kDeclaringClassDefIndexForArrays);
    941   }
    942 
    943   void VisitArraySet(HArraySet* instruction) OVERRIDE {
    944     HInstruction* array = instruction->InputAt(0);
    945     HInstruction* index = instruction->InputAt(1);
    946     HInstruction* value = instruction->InputAt(2);
    947     VisitSetLocation(instruction,
    948                      array,
    949                      HeapLocation::kInvalidFieldOffset,
    950                      index,
    951                      HeapLocation::kDeclaringClassDefIndexForArrays,
    952                      value);
    953   }
    954 
    955   void VisitDeoptimize(HDeoptimize* instruction) {
    956     const ArenaVector<HInstruction*>& heap_values =
    957         heap_values_for_[instruction->GetBlock()->GetBlockId()];
    958     for (HInstruction* heap_value : heap_values) {
    959       // Filter out fake instructions before checking instruction kind below.
    960       if (heap_value == kUnknownHeapValue || heap_value == kDefaultHeapValue) {
    961         continue;
    962       }
    963       // A store is kept as the heap value for possibly removed stores.
    964       if (heap_value->IsInstanceFieldSet() || heap_value->IsArraySet()) {
    965         // Check whether the reference for a store is used by an environment local of
    966         // HDeoptimize.
    967         HInstruction* reference = heap_value->InputAt(0);
    968         DCHECK(heap_location_collector_.FindReferenceInfoOf(reference)->IsSingleton());
    969         for (const HUseListNode<HEnvironment*>& use : reference->GetEnvUses()) {
    970           HEnvironment* user = use.GetUser();
    971           if (user->GetHolder() == instruction) {
    972             // The singleton for the store is visible at this deoptimization
    973             // point. Need to keep the store so that the heap value is
    974             // seen by the interpreter.
    975             KeepIfIsStore(heap_value);
    976           }
    977         }
    978       }
    979     }
    980   }
    981 
    982   void HandleInvoke(HInstruction* invoke) {
    983     ArenaVector<HInstruction*>& heap_values =
    984         heap_values_for_[invoke->GetBlock()->GetBlockId()];
    985     for (size_t i = 0; i < heap_values.size(); i++) {
    986       ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo();
    987       if (ref_info->IsSingleton()) {
    988         // Singleton references cannot be seen by the callee.
    989       } else {
    990         heap_values[i] = kUnknownHeapValue;
    991       }
    992     }
    993   }
    994 
    995   void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
    996     HandleInvoke(invoke);
    997   }
    998 
    999   void VisitInvokeVirtual(HInvokeVirtual* invoke) OVERRIDE {
   1000     HandleInvoke(invoke);
   1001   }
   1002 
   1003   void VisitInvokeInterface(HInvokeInterface* invoke) OVERRIDE {
   1004     HandleInvoke(invoke);
   1005   }
   1006 
   1007   void VisitInvokeUnresolved(HInvokeUnresolved* invoke) OVERRIDE {
   1008     HandleInvoke(invoke);
   1009   }
   1010 
   1011   void VisitInvokePolymorphic(HInvokePolymorphic* invoke) OVERRIDE {
   1012     HandleInvoke(invoke);
   1013   }
   1014 
   1015   void VisitClinitCheck(HClinitCheck* clinit) OVERRIDE {
   1016     HandleInvoke(clinit);
   1017   }
   1018 
   1019   void VisitUnresolvedInstanceFieldGet(HUnresolvedInstanceFieldGet* instruction) OVERRIDE {
   1020     // Conservatively treat it as an invocation.
   1021     HandleInvoke(instruction);
   1022   }
   1023 
   1024   void VisitUnresolvedInstanceFieldSet(HUnresolvedInstanceFieldSet* instruction) OVERRIDE {
   1025     // Conservatively treat it as an invocation.
   1026     HandleInvoke(instruction);
   1027   }
   1028 
   1029   void VisitUnresolvedStaticFieldGet(HUnresolvedStaticFieldGet* instruction) OVERRIDE {
   1030     // Conservatively treat it as an invocation.
   1031     HandleInvoke(instruction);
   1032   }
   1033 
   1034   void VisitUnresolvedStaticFieldSet(HUnresolvedStaticFieldSet* instruction) OVERRIDE {
   1035     // Conservatively treat it as an invocation.
   1036     HandleInvoke(instruction);
   1037   }
   1038 
   1039   void VisitNewInstance(HNewInstance* new_instance) OVERRIDE {
   1040     ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(new_instance);
   1041     if (ref_info == nullptr) {
   1042       // new_instance isn't used for field accesses. No need to process it.
   1043       return;
   1044     }
   1045     if (ref_info->IsSingletonAndRemovable() &&
   1046         !new_instance->IsFinalizable() &&
   1047         !new_instance->NeedsChecks()) {
   1048       singleton_new_instances_.push_back(new_instance);
   1049     }
   1050     ArenaVector<HInstruction*>& heap_values =
   1051         heap_values_for_[new_instance->GetBlock()->GetBlockId()];
   1052     for (size_t i = 0; i < heap_values.size(); i++) {
   1053       HInstruction* ref =
   1054           heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo()->GetReference();
   1055       size_t offset = heap_location_collector_.GetHeapLocation(i)->GetOffset();
   1056       if (ref == new_instance && offset >= mirror::kObjectHeaderSize) {
   1057         // Instance fields except the header fields are set to default heap values.
   1058         heap_values[i] = kDefaultHeapValue;
   1059       }
   1060     }
   1061   }
   1062 
   1063   void VisitNewArray(HNewArray* new_array) OVERRIDE {
   1064     ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(new_array);
   1065     if (ref_info == nullptr) {
   1066       // new_array isn't used for array accesses. No need to process it.
   1067       return;
   1068     }
   1069     if (ref_info->IsSingletonAndRemovable()) {
   1070       singleton_new_arrays_.push_back(new_array);
   1071     }
   1072     ArenaVector<HInstruction*>& heap_values =
   1073         heap_values_for_[new_array->GetBlock()->GetBlockId()];
   1074     for (size_t i = 0; i < heap_values.size(); i++) {
   1075       HeapLocation* location = heap_location_collector_.GetHeapLocation(i);
   1076       HInstruction* ref = location->GetReferenceInfo()->GetReference();
   1077       if (ref == new_array && location->GetIndex() != nullptr) {
   1078         // Array elements are set to default heap values.
   1079         heap_values[i] = kDefaultHeapValue;
   1080       }
   1081     }
   1082   }
   1083 
   1084   // Find an instruction's substitute if it should be removed.
   1085   // Return the same instruction if it should not be removed.
   1086   HInstruction* FindSubstitute(HInstruction* instruction) {
   1087     size_t size = removed_loads_.size();
   1088     for (size_t i = 0; i < size; i++) {
   1089       if (removed_loads_[i] == instruction) {
   1090         return substitute_instructions_for_loads_[i];
   1091       }
   1092     }
   1093     return instruction;
   1094   }
   1095 
   1096   const HeapLocationCollector& heap_location_collector_;
   1097   const SideEffectsAnalysis& side_effects_;
   1098 
   1099   // One array of heap values for each block.
   1100   ArenaVector<ArenaVector<HInstruction*>> heap_values_for_;
   1101 
   1102   // We record the instructions that should be eliminated but may be
   1103   // used by heap locations. They'll be removed in the end.
   1104   ArenaVector<HInstruction*> removed_loads_;
   1105   ArenaVector<HInstruction*> substitute_instructions_for_loads_;
   1106 
   1107   // Stores in this list may be removed from the list later when it's
   1108   // found that the store cannot be eliminated.
   1109   ArenaVector<HInstruction*> possibly_removed_stores_;
   1110 
   1111   ArenaVector<HInstruction*> singleton_new_instances_;
   1112   ArenaVector<HInstruction*> singleton_new_arrays_;
   1113 
   1114   DISALLOW_COPY_AND_ASSIGN(LSEVisitor);
   1115 };
   1116 
   1117 void LoadStoreElimination::Run() {
   1118   if (graph_->IsDebuggable() || graph_->HasTryCatch()) {
   1119     // Debugger may set heap values or trigger deoptimization of callers.
   1120     // Try/catch support not implemented yet.
   1121     // Skip this optimization.
   1122     return;
   1123   }
   1124   HeapLocationCollector heap_location_collector(graph_);
   1125   for (HBasicBlock* block : graph_->GetReversePostOrder()) {
   1126     heap_location_collector.VisitBasicBlock(block);
   1127   }
   1128   if (heap_location_collector.GetNumberOfHeapLocations() > kMaxNumberOfHeapLocations) {
   1129     // Bail out if there are too many heap locations to deal with.
   1130     return;
   1131   }
   1132   if (!heap_location_collector.HasHeapStores()) {
   1133     // Without heap stores, this pass would act mostly as GVN on heap accesses.
   1134     return;
   1135   }
   1136   if (heap_location_collector.HasVolatile() || heap_location_collector.HasMonitorOps()) {
   1137     // Don't do load/store elimination if the method has volatile field accesses or
   1138     // monitor operations, for now.
   1139     // TODO: do it right.
   1140     return;
   1141   }
   1142   heap_location_collector.BuildAliasingMatrix();
   1143   LSEVisitor lse_visitor(graph_, heap_location_collector, side_effects_);
   1144   for (HBasicBlock* block : graph_->GetReversePostOrder()) {
   1145     lse_visitor.VisitBasicBlock(block);
   1146   }
   1147   lse_visitor.RemoveInstructions();
   1148 }
   1149 
   1150 }  // namespace art
   1151