Refactoring LSE/LSA: introduce heap location type

Rationale:
This refactoring introduces data types to heap locations.
This will allow better type disambiguation in the future.
As a first showcase, it already removes rather error-prone
"exceptional" code in LSE dealing with array types on null
values. Furthermore, many LSA specific details started to "leak"
into clients, which is also error-prone. This refactoring moves
such details back into just LSA, where it belongs.

Test: test-art-host,target

Bug: b/77906240

Change-Id: Id327bbe86dde451a942c9c5f9e83054c36241882
diff --git a/compiler/optimizing/data_type.h b/compiler/optimizing/data_type.h
index be26e67..5ac6e46 100644
--- a/compiler/optimizing/data_type.h
+++ b/compiler/optimizing/data_type.h
@@ -216,6 +216,21 @@
         Size(result_type) > Size(input_type);
   }
 
+  static Type ToSigned(Type type) {
+    switch (type) {
+      case Type::kUint8:
+        return Type::kInt8;
+      case Type::kUint16:
+        return Type::kInt16;
+      case Type::kUint32:
+        return Type::kInt32;
+      case Type::kUint64:
+        return Type::kInt64;
+      default:
+        return type;
+    }
+  }
+
   static const char* PrettyDescriptor(Type type);
 
  private:
diff --git a/compiler/optimizing/load_store_analysis.h b/compiler/optimizing/load_store_analysis.h
index f84846d..769a3f1 100644
--- a/compiler/optimizing/load_store_analysis.h
+++ b/compiler/optimizing/load_store_analysis.h
@@ -94,11 +94,13 @@
   static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
 
   HeapLocation(ReferenceInfo* ref_info,
+               DataType::Type type,
                size_t offset,
                HInstruction* index,
                size_t vector_length,
                int16_t declaring_class_def_index)
       : ref_info_(ref_info),
+        type_(DataType::ToSigned(type)),
         offset_(offset),
         index_(index),
         vector_length_(vector_length),
@@ -116,6 +118,7 @@
   }
 
   ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
+  DataType::Type GetType() const { return type_; }
   size_t GetOffset() const { return offset_; }
   HInstruction* GetIndex() const { return index_; }
   size_t GetVectorLength() const { return vector_length_; }
@@ -149,6 +152,10 @@
  private:
   // Reference for instance/static field, array element or vector data.
   ReferenceInfo* const ref_info_;
+  // Type of data residing at HeapLocation (always signed for integral
+  // data since e.g. a[i] and a[i] & 0xff are represented by differently
+  // signed types; char vs short are disambiguated through the reference).
+  const DataType::Type type_;
   // Offset of static/instance field.
   // Invalid when this HeapLocation is not field.
   const size_t offset_;
@@ -237,19 +244,31 @@
     DCHECK(object != nullptr);
     DCHECK(field != nullptr);
     return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(object)),
+                                 field->GetFieldType(),
                                  field->GetFieldOffset().SizeValue(),
                                  nullptr,
                                  HeapLocation::kScalar,
                                  field->GetDeclaringClassDefIndex());
   }
 
-  size_t GetArrayHeapLocation(HInstruction* array,
-                              HInstruction* index,
-                              size_t vector_length = HeapLocation::kScalar) const {
-    DCHECK(array != nullptr);
-    DCHECK(index != nullptr);
-    DCHECK_GE(vector_length, HeapLocation::kScalar);
+  size_t GetArrayHeapLocation(HInstruction* instruction) const {
+    DCHECK(instruction != nullptr);
+    HInstruction* array = instruction->InputAt(0);
+    HInstruction* index = instruction->InputAt(1);
+    DataType::Type type = instruction->GetType();
+    size_t vector_length = HeapLocation::kScalar;
+    if (instruction->IsArraySet()) {
+      type = instruction->AsArraySet()->GetComponentType();
+    } else if (instruction->IsVecStore() ||
+               instruction->IsVecLoad()) {
+      HVecOperation* vec_op = instruction->AsVecOperation();
+      type = vec_op->GetPackedType();
+      vector_length = vec_op->GetVectorLength();
+    } else {
+      DCHECK(instruction->IsArrayGet());
+    }
     return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
+                                 type,
                                  HeapLocation::kInvalidFieldOffset,
                                  index,
                                  vector_length,
@@ -279,13 +298,16 @@
   // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
   // these indexes alias.
   size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
+                               DataType::Type type,
                                size_t offset,
                                HInstruction* index,
                                size_t vector_length,
                                int16_t declaring_class_def_index) const {
+    DataType::Type lookup_type = DataType::ToSigned(type);
     for (size_t i = 0; i < heap_locations_.size(); i++) {
       HeapLocation* loc = heap_locations_[i];
       if (loc->GetReferenceInfo() == ref_info &&
+          loc->GetType() == lookup_type &&
           loc->GetOffset() == offset &&
           loc->GetIndex() == index &&
           loc->GetVectorLength() == vector_length &&
@@ -425,6 +447,7 @@
   }
 
   HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
+                                        DataType::Type type,
                                         size_t offset,
                                         HInstruction* index,
                                         size_t vector_length,
@@ -432,10 +455,10 @@
     HInstruction* original_ref = HuntForOriginalReference(ref);
     ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
     size_t heap_location_idx = FindHeapLocationIndex(
-        ref_info, offset, index, vector_length, declaring_class_def_index);
+        ref_info, type, offset, index, vector_length, declaring_class_def_index);
     if (heap_location_idx == kHeapLocationNotFound) {
       HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
-          HeapLocation(ref_info, offset, index, vector_length, declaring_class_def_index);
+          HeapLocation(ref_info, type, offset, index, vector_length, declaring_class_def_index);
       heap_locations_.push_back(heap_loc);
       return heap_loc;
     }
@@ -446,17 +469,23 @@
     if (field_info.IsVolatile()) {
       has_volatile_ = true;
     }
+    DataType::Type type = field_info.GetFieldType();
     const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
     const size_t offset = field_info.GetFieldOffset().SizeValue();
     return GetOrCreateHeapLocation(ref,
+                                   type,
                                    offset,
                                    nullptr,
                                    HeapLocation::kScalar,
                                    declaring_class_def_index);
   }
 
-  void VisitArrayAccess(HInstruction* array, HInstruction* index, size_t vector_length) {
+  void VisitArrayAccess(HInstruction* array,
+                        HInstruction* index,
+                        DataType::Type type,
+                        size_t vector_length) {
     GetOrCreateHeapLocation(array,
+                            type,
                             HeapLocation::kInvalidFieldOffset,
                             index,
                             vector_length,
@@ -510,28 +539,32 @@
   void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
     HInstruction* array = instruction->InputAt(0);
     HInstruction* index = instruction->InputAt(1);
-    VisitArrayAccess(array, index, HeapLocation::kScalar);
+    DataType::Type type = instruction->GetType();
+    VisitArrayAccess(array, index, type, HeapLocation::kScalar);
     CreateReferenceInfoForReferenceType(instruction);
   }
 
   void VisitArraySet(HArraySet* instruction) OVERRIDE {
     HInstruction* array = instruction->InputAt(0);
     HInstruction* index = instruction->InputAt(1);
-    VisitArrayAccess(array, index, HeapLocation::kScalar);
+    DataType::Type type = instruction->GetComponentType();
+    VisitArrayAccess(array, index, type, HeapLocation::kScalar);
     has_heap_stores_ = true;
   }
 
   void VisitVecLoad(HVecLoad* instruction) OVERRIDE {
     HInstruction* array = instruction->InputAt(0);
     HInstruction* index = instruction->InputAt(1);
-    VisitArrayAccess(array, index, instruction->GetVectorLength());
+    DataType::Type type = instruction->GetPackedType();
+    VisitArrayAccess(array, index, type, instruction->GetVectorLength());
     CreateReferenceInfoForReferenceType(instruction);
   }
 
   void VisitVecStore(HVecStore* instruction) OVERRIDE {
     HInstruction* array = instruction->InputAt(0);
     HInstruction* index = instruction->InputAt(1);
-    VisitArrayAccess(array, index, instruction->GetVectorLength());
+    DataType::Type type = instruction->GetPackedType();
+    VisitArrayAccess(array, index, type, instruction->GetVectorLength());
     has_heap_stores_ = true;
   }
 
diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc
index 56361a8..bfe7a4f 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -78,12 +78,16 @@
 
   // Test queries on HeapLocationCollector's ref info and index records.
   ReferenceInfo* ref = heap_location_collector.FindReferenceInfoOf(array);
+  DataType::Type type = DataType::Type::kInt32;
   size_t field = HeapLocation::kInvalidFieldOffset;
   size_t vec = HeapLocation::kScalar;
   size_t class_def = HeapLocation::kDeclaringClassDefIndexForArrays;
-  size_t loc1 = heap_location_collector.FindHeapLocationIndex(ref, field, c1, vec, class_def);
-  size_t loc2 = heap_location_collector.FindHeapLocationIndex(ref, field, c2, vec, class_def);
-  size_t loc3 = heap_location_collector.FindHeapLocationIndex(ref, field, index, vec, class_def);
+  size_t loc1 = heap_location_collector.FindHeapLocationIndex(
+      ref, type, field, c1, vec, class_def);
+  size_t loc2 = heap_location_collector.FindHeapLocationIndex(
+      ref, type, field, c2, vec, class_def);
+  size_t loc3 = heap_location_collector.FindHeapLocationIndex(
+      ref, type, field, index, vec, class_def);
   // must find this reference info for array in HeapLocationCollector.
   ASSERT_TRUE(ref != nullptr);
   // must find these heap locations;
@@ -246,28 +250,28 @@
   size_t loc2 = HeapLocationCollector::kHeapLocationNotFound;
 
   // Test alias: array[0] and array[1]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c1);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set1);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set2);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+0] and array[i-0]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub0);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set3);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set5);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+1] and array[i-1]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add1);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub1);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set4);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set6);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+1] and array[1-i]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add1);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, rev_sub1);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set4);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set7);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+1] and array[i-(-1)]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add1);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_neg1);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set4);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set8);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 }
 
@@ -409,70 +413,75 @@
   size_t loc1, loc2;
 
   // Test alias: array[0] and array[0,1,2,3]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c0, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_0);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_0);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
+  // Test alias: array[0] and array[1,2,3,4]
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_0);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_1);
+  ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
+
   // Test alias: array[0] and array[8,9,10,11]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c8, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_0);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_8);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[1] and array[8,9,10,11]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c1);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c8, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_1);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_8);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[1] and array[0,1,2,3]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c1);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c0, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_1);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_0);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[0,1,2,3] and array[8,9,10,11]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c0, 4);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c8, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(vstore_0);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_8);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[0,1,2,3] and array[1,2,3,4]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c1, 4);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c0, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(vstore_0);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_1);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[0] and array[i,i+1,i+2,i+3]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, c0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, index, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_0);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_i);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i] and array[0,1,2,3]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, index);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, c0, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_0);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i] and array[i,i+1,i+2,i+3]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, index);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, index, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_i);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i] and array[i+8,i+9,i+10,i+11]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, index);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, i_add8, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_i_add8);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+6,i+7,i+8,i+9] and array[i+8,i+9,i+10,i+11]
   // Test partial overlap.
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, i_add6, 4);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, i_add8, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(vstore_i_add6);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_i_add8);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+6,i+7] and array[i,i+1,i+2,i+3]
   // Test different vector lengths.
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, i_add6, 2);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, index, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(vstore_i_add6_vlen2);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_i);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+6,i+7] and array[i+8,i+9,i+10,i+11]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, i_add6, 2);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, i_add8, 4);
+  loc1 = heap_location_collector.GetArrayHeapLocation(vstore_i_add6_vlen2);
+  loc2 = heap_location_collector.GetArrayHeapLocation(vstore_i_add8);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 }
 
@@ -563,33 +572,33 @@
   size_t loc2 = HeapLocationCollector::kHeapLocationNotFound;
 
   // Test alias: array[i+0x80000000] and array[i-0x80000000]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add_0x80000000);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_0x80000000);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_1);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_2);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+0x10] and array[i-0xFFFFFFF0]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add_0x10);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_0xFFFFFFF0);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_3);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_4);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+0x7FFFFFFF] and array[i-0x80000001]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add_0x7FFFFFFF);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_0x80000001);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_5);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_6);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Test alias: array[i+0] and array[i-0]
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add_0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_0);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_7);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_8);
   ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Should not alias:
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, sub_0x80000000);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_0x80000001);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_2);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_6);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 
   // Should not alias:
-  loc1 = heap_location_collector.GetArrayHeapLocation(array, add_0);
-  loc2 = heap_location_collector.GetArrayHeapLocation(array, sub_0x80000000);
+  loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_7);
+  loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_2);
   ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
 }
 
@@ -647,10 +656,10 @@
   // times the original reference has been transformed by BoundType,
   // NullCheck, IntermediateAddress, etc.
   ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 1U);
-  size_t loc1 = heap_location_collector.GetArrayHeapLocation(array, c1);
-  size_t loc2 = heap_location_collector.GetArrayHeapLocation(bound_type, c1);
-  size_t loc3 = heap_location_collector.GetArrayHeapLocation(null_check, c1);
-  size_t loc4 = heap_location_collector.GetArrayHeapLocation(inter_addr, c1);
+  size_t loc1 = heap_location_collector.GetArrayHeapLocation(array_get1);
+  size_t loc2 = heap_location_collector.GetArrayHeapLocation(array_get2);
+  size_t loc3 = heap_location_collector.GetArrayHeapLocation(array_get3);
+  size_t loc4 = heap_location_collector.GetArrayHeapLocation(array_get4);
   ASSERT_TRUE(loc1 != HeapLocationCollector::kHeapLocationNotFound);
   ASSERT_EQ(loc1, loc2);
   ASSERT_EQ(loc1, loc3);
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index d598ff5..35e64f7 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -160,7 +160,7 @@
 
   // Scan the list of removed loads to see if we can reuse `type_conversion`, if
   // the other removed load has the same substitute and type and is dominated
-  // by `type_conversioni`.
+  // by `type_conversion`.
   void TryToReuseTypeConversion(HInstruction* type_conversion, size_t index) {
     size_t size = removed_loads_.size();
     HInstruction* load = removed_loads_[index];
@@ -542,16 +542,7 @@
     }
   }
 
-  void VisitGetLocation(HInstruction* instruction,
-                        HInstruction* ref,
-                        size_t offset,
-                        HInstruction* index,
-                        size_t vector_length,
-                        int16_t declaring_class_def_index) {
-    HInstruction* original_ref = heap_location_collector_.HuntForOriginalReference(ref);
-    ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(original_ref);
-    size_t idx = heap_location_collector_.FindHeapLocationIndex(
-        ref_info, offset, index, vector_length, declaring_class_def_index);
+  void VisitGetLocation(HInstruction* instruction, size_t idx) {
     DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
     ScopedArenaVector<HInstruction*>& heap_values =
         heap_values_for_[instruction->GetBlock()->GetBlockId()];
@@ -569,23 +560,7 @@
       heap_values[idx] = instruction;
       KeepStoresIfAliasedToLocation(heap_values, idx);
     } else {
-      if (DataType::Kind(heap_value->GetType()) != DataType::Kind(instruction->GetType())) {
-        // The only situation where the same heap location has different type is when
-        // we do an array get on an instruction that originates from the null constant
-        // (the null could be behind a field access, an array access, a null check or
-        // a bound type).
-        // In order to stay properly typed on primitive types, we do not eliminate
-        // the array gets.
-        if (kIsDebugBuild) {
-          DCHECK(heap_value->IsArrayGet()) << heap_value->DebugName();
-          DCHECK(instruction->IsArrayGet()) << instruction->DebugName();
-        }
-        // Load isn't eliminated. Put the load as the value into the HeapLocation.
-        // This acts like GVN but with better aliasing analysis.
-        heap_values[idx] = instruction;
-        KeepStoresIfAliasedToLocation(heap_values, idx);
-        return;
-      }
+      // Load is eliminated.
       AddRemovedLoad(instruction, heap_value);
       TryRemovingNullCheck(instruction);
     }
@@ -610,21 +585,11 @@
     return false;
   }
 
-  void VisitSetLocation(HInstruction* instruction,
-                        HInstruction* ref,
-                        size_t offset,
-                        HInstruction* index,
-                        size_t vector_length,
-                        int16_t declaring_class_def_index,
-                        HInstruction* value) {
+  void VisitSetLocation(HInstruction* instruction, size_t idx, HInstruction* value) {
+    DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
     DCHECK(!IsStore(value)) << value->DebugName();
     // value may already have a substitute.
     value = FindSubstitute(value);
-    HInstruction* original_ref = heap_location_collector_.HuntForOriginalReference(ref);
-    ReferenceInfo* ref_info = heap_location_collector_.FindReferenceInfoOf(original_ref);
-    size_t idx = heap_location_collector_.FindHeapLocationIndex(
-        ref_info, offset, index, vector_length, declaring_class_def_index);
-    DCHECK_NE(idx, HeapLocationCollector::kHeapLocationNotFound);
     ScopedArenaVector<HInstruction*>& heap_values =
         heap_values_for_[instruction->GetBlock()->GetBlockId()];
     HInstruction* heap_value = heap_values[idx];
@@ -644,7 +609,8 @@
       } else if (!loop_info->IsIrreducible()) {
         // instruction is a store in the loop so the loop must do write.
         DCHECK(side_effects_.GetLoopEffects(loop_info->GetHeader()).DoesAnyWrite());
-        if (ref_info->IsSingleton() && !loop_info->IsDefinedOutOfTheLoop(original_ref)) {
+        ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(idx)->GetReferenceInfo();
+        if (ref_info->IsSingleton() && !loop_info->IsDefinedOutOfTheLoop(ref_info->GetReference())) {
           // original_ref is created inside the loop. Value stored to it isn't needed at
           // the loop header. This is true for outer loops also.
           possibly_redundant = true;
@@ -686,79 +652,39 @@
   }
 
   void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
-    HInstruction* obj = instruction->InputAt(0);
-    size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
-    int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
-    VisitGetLocation(instruction,
-                     obj,
-                     offset,
-                     nullptr,
-                     HeapLocation::kScalar,
-                     declaring_class_def_index);
+    HInstruction* object = instruction->InputAt(0);
+    const FieldInfo& field = instruction->GetFieldInfo();
+    VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(object, &field));
   }
 
   void VisitInstanceFieldSet(HInstanceFieldSet* instruction) OVERRIDE {
-    HInstruction* obj = instruction->InputAt(0);
-    size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
-    int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
+    HInstruction* object = instruction->InputAt(0);
+    const FieldInfo& field = instruction->GetFieldInfo();
     HInstruction* value = instruction->InputAt(1);
-    VisitSetLocation(instruction,
-                     obj,
-                     offset,
-                     nullptr,
-                     HeapLocation::kScalar,
-                     declaring_class_def_index,
-                     value);
+    size_t idx = heap_location_collector_.GetFieldHeapLocation(object, &field);
+    VisitSetLocation(instruction, idx, value);
   }
 
   void VisitStaticFieldGet(HStaticFieldGet* instruction) OVERRIDE {
     HInstruction* cls = instruction->InputAt(0);
-    size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
-    int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
-    VisitGetLocation(instruction,
-                     cls,
-                     offset,
-                     nullptr,
-                     HeapLocation::kScalar,
-                     declaring_class_def_index);
+    const FieldInfo& field = instruction->GetFieldInfo();
+    VisitGetLocation(instruction, heap_location_collector_.GetFieldHeapLocation(cls, &field));
   }
 
   void VisitStaticFieldSet(HStaticFieldSet* instruction) OVERRIDE {
     HInstruction* cls = instruction->InputAt(0);
-    size_t offset = instruction->GetFieldInfo().GetFieldOffset().SizeValue();
-    int16_t declaring_class_def_index = instruction->GetFieldInfo().GetDeclaringClassDefIndex();
-    HInstruction* value = instruction->InputAt(1);
-    VisitSetLocation(instruction,
-                     cls,
-                     offset,
-                     nullptr,
-                     HeapLocation::kScalar,
-                     declaring_class_def_index,
-                     value);
+    const FieldInfo& field = instruction->GetFieldInfo();
+    size_t idx = heap_location_collector_.GetFieldHeapLocation(cls, &field);
+    VisitSetLocation(instruction, idx, instruction->InputAt(1));
   }
 
   void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
-    HInstruction* array = instruction->InputAt(0);
-    HInstruction* index = instruction->InputAt(1);
-    VisitGetLocation(instruction,
-                     array,
-                     HeapLocation::kInvalidFieldOffset,
-                     index,
-                     HeapLocation::kScalar,
-                     HeapLocation::kDeclaringClassDefIndexForArrays);
+    VisitGetLocation(instruction, heap_location_collector_.GetArrayHeapLocation(instruction));
   }
 
   void VisitArraySet(HArraySet* instruction) OVERRIDE {
-    HInstruction* array = instruction->InputAt(0);
-    HInstruction* index = instruction->InputAt(1);
-    HInstruction* value = instruction->InputAt(2);
-    VisitSetLocation(instruction,
-                     array,
-                     HeapLocation::kInvalidFieldOffset,
-                     index,
-                     HeapLocation::kScalar,
-                     HeapLocation::kDeclaringClassDefIndexForArrays,
-                     value);
+    size_t idx = heap_location_collector_.GetArrayHeapLocation(instruction);
+    VisitSetLocation(instruction, idx, instruction->InputAt(2));
   }
 
   void VisitDeoptimize(HDeoptimize* instruction) {
@@ -971,6 +897,7 @@
     lse_visitor.VisitBasicBlock(block);
   }
   lse_visitor.RemoveInstructions();
+
   return true;
 }
 
diff --git a/compiler/optimizing/scheduler.cc b/compiler/optimizing/scheduler.cc
index e014efa..588ea03 100644
--- a/compiler/optimizing/scheduler.cc
+++ b/compiler/optimizing/scheduler.cc
@@ -70,19 +70,19 @@
   return false;
 }
 
-size_t SchedulingGraph::ArrayAccessHeapLocation(HInstruction* array, HInstruction* index) const {
+size_t SchedulingGraph::ArrayAccessHeapLocation(HInstruction* instruction) const {
   DCHECK(heap_location_collector_ != nullptr);
-  size_t heap_loc = heap_location_collector_->GetArrayHeapLocation(array, index);
+  size_t heap_loc = heap_location_collector_->GetArrayHeapLocation(instruction);
   // This array access should be analyzed and added to HeapLocationCollector before.
   DCHECK(heap_loc != HeapLocationCollector::kHeapLocationNotFound);
   return heap_loc;
 }
 
-bool SchedulingGraph::ArrayAccessMayAlias(const HInstruction* node,
-                                          const HInstruction* other) const {
+bool SchedulingGraph::ArrayAccessMayAlias(HInstruction* node,
+                                          HInstruction* other) const {
   DCHECK(heap_location_collector_ != nullptr);
-  size_t node_heap_loc = ArrayAccessHeapLocation(node->InputAt(0), node->InputAt(1));
-  size_t other_heap_loc = ArrayAccessHeapLocation(other->InputAt(0), other->InputAt(1));
+  size_t node_heap_loc = ArrayAccessHeapLocation(node);
+  size_t other_heap_loc = ArrayAccessHeapLocation(other);
 
   // For example: arr[0] and arr[0]
   if (node_heap_loc == other_heap_loc) {
@@ -194,8 +194,8 @@
   return true;
 }
 
-bool SchedulingGraph::HasMemoryDependency(const HInstruction* node,
-                                          const HInstruction* other) const {
+bool SchedulingGraph::HasMemoryDependency(HInstruction* node,
+                                          HInstruction* other) const {
   if (!MayHaveReorderingDependency(node->GetSideEffects(), other->GetSideEffects())) {
     return false;
   }
@@ -264,8 +264,8 @@
 
 // Check whether `node` depends on `other`, taking into account `SideEffect`
 // information and `CanThrow` information.
-bool SchedulingGraph::HasSideEffectDependency(const HInstruction* node,
-                                              const HInstruction* other) const {
+bool SchedulingGraph::HasSideEffectDependency(HInstruction* node,
+                                              HInstruction* other) const {
   if (HasMemoryDependency(node, other)) {
     return true;
   }
diff --git a/compiler/optimizing/scheduler.h b/compiler/optimizing/scheduler.h
index 51cd20a..8e98f19 100644
--- a/compiler/optimizing/scheduler.h
+++ b/compiler/optimizing/scheduler.h
@@ -310,12 +310,12 @@
   void AddOtherDependency(SchedulingNode* node, SchedulingNode* dependency) {
     AddDependency(node, dependency, /*is_data_dependency*/false);
   }
-  bool HasMemoryDependency(const HInstruction* node, const HInstruction* other) const;
+  bool HasMemoryDependency(HInstruction* node, HInstruction* other) const;
   bool HasExceptionDependency(const HInstruction* node, const HInstruction* other) const;
-  bool HasSideEffectDependency(const HInstruction* node, const HInstruction* other) const;
-  bool ArrayAccessMayAlias(const HInstruction* node, const HInstruction* other) const;
+  bool HasSideEffectDependency(HInstruction* node, HInstruction* other) const;
+  bool ArrayAccessMayAlias(HInstruction* node, HInstruction* other) const;
   bool FieldAccessMayAlias(const HInstruction* node, const HInstruction* other) const;
-  size_t ArrayAccessHeapLocation(HInstruction* array, HInstruction* index) const;
+  size_t ArrayAccessHeapLocation(HInstruction* instruction) const;
   size_t FieldAccessHeapLocation(HInstruction* obj, const FieldInfo* field) const;
 
   // Add dependencies nodes for the given `HInstruction`: inputs, environments, and side-effects.
diff --git a/compiler/optimizing/scheduler_test.cc b/compiler/optimizing/scheduler_test.cc
index fb15fc8..d4cae72 100644
--- a/compiler/optimizing/scheduler_test.cc
+++ b/compiler/optimizing/scheduler_test.cc
@@ -296,38 +296,38 @@
     size_t loc2 = HeapLocationCollector::kHeapLocationNotFound;
 
     // Test side effect dependency: array[0] and array[1]
-    loc1 = heap_location_collector.GetArrayHeapLocation(arr, c0);
-    loc2 = heap_location_collector.GetArrayHeapLocation(arr, c1);
+    loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_0);
+    loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_1);
     ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
     ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_1, arr_set_0));
 
     // Test side effect dependency based on LSA analysis: array[i] and array[j]
-    loc1 = heap_location_collector.GetArrayHeapLocation(arr, i);
-    loc2 = heap_location_collector.GetArrayHeapLocation(arr, j);
+    loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+    loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_j);
     ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
     ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_j, arr_set_i));
 
     // Test side effect dependency based on LSA analysis: array[i] and array[i+0]
-    loc1 = heap_location_collector.GetArrayHeapLocation(arr, i);
-    loc2 = heap_location_collector.GetArrayHeapLocation(arr, add0);
+    loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+    loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_add0);
     ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
     ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_add0, arr_set_i));
 
     // Test side effect dependency based on LSA analysis: array[i] and array[i-0]
-    loc1 = heap_location_collector.GetArrayHeapLocation(arr, i);
-    loc2 = heap_location_collector.GetArrayHeapLocation(arr, sub0);
+    loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+    loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_sub0);
     ASSERT_TRUE(heap_location_collector.MayAlias(loc1, loc2));
     ASSERT_TRUE(scheduling_graph.HasImmediateOtherDependency(arr_set_sub0, arr_set_i));
 
     // Test side effect dependency based on LSA analysis: array[i] and array[i+1]
-    loc1 = heap_location_collector.GetArrayHeapLocation(arr, i);
-    loc2 = heap_location_collector.GetArrayHeapLocation(arr, add1);
+    loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_i);
+    loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_add1);
     ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
     ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_add1, arr_set_i));
 
     // Test side effect dependency based on LSA analysis: array[i+1] and array[i-1]
-    loc1 = heap_location_collector.GetArrayHeapLocation(arr, add1);
-    loc2 = heap_location_collector.GetArrayHeapLocation(arr, sub1);
+    loc1 = heap_location_collector.GetArrayHeapLocation(arr_set_add1);
+    loc2 = heap_location_collector.GetArrayHeapLocation(arr_set_sub1);
     ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
     ASSERT_FALSE(scheduling_graph.HasImmediateOtherDependency(arr_set_sub1, arr_set_add1));
 
diff --git a/test/586-checker-null-array-get/src/Main.java b/test/586-checker-null-array-get/src/Main.java
index de9429f..ebe91cf 100644
--- a/test/586-checker-null-array-get/src/Main.java
+++ b/test/586-checker-null-array-get/src/Main.java
@@ -107,9 +107,8 @@
   /// CHECK-DAG: <<GetJ3:j\d+>>      ArrayGet [<<CheckJ>>,{{i\d+}}]
   public static void bar() {
     // We create multiple accesses that will lead the bounds check
-    // elimination pass to add a HDeoptimize. Not having the bounds check helped
-    // the load store elimination think it could merge two ArrayGet with different
-    // types.
+    // elimination pass to add a HDeoptimize. Not having the bounds check
+    // makes the ArrayGets look almost the same if it were not for the type!
     String[] array = (String[])getNull();
     objectField = array[0];
     objectField = array[1];