Fix LSA hunt for original reference bug.
Fix a bug in LSA where it doesn't take IntermediateAddress
into account during hunting for original reference.
In following example, original reference i0 can be transformed
by NullCheck, BoundType, IntermediateAddress, etc.
i0 NewArray
i1 HInstruction(i0)
i2 ArrayGet(i1, index)
Test: test-art-host
Test: test-art-target
Test: load_store_analysis_test
Test: 706-checker-scheduler
Change-Id: I162dd8a86fcd31daee3517357c6af638c950b31b
diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc
index 86696d0..b41e1e4 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -389,4 +389,68 @@
ASSERT_FALSE(heap_location_collector.MayAlias(loc1, loc2));
}
+TEST_F(LoadStoreAnalysisTest, TestHuntOriginalRef) {
+ HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_);
+ graph_->AddBlock(entry);
+ graph_->SetEntryBlock(entry);
+
+ // Different ways where orignal array reference are transformed & passed to ArrayGet.
+ // ParameterValue --> ArrayGet
+ // ParameterValue --> BoundType --> ArrayGet
+ // ParameterValue --> BoundType --> NullCheck --> ArrayGet
+ // ParameterValue --> BoundType --> NullCheck --> IntermediateAddress --> ArrayGet
+ HInstruction* c1 = graph_->GetIntConstant(1);
+ HInstruction* array = new (GetAllocator()) HParameterValue(graph_->GetDexFile(),
+ dex::TypeIndex(0),
+ 0,
+ DataType::Type::kReference);
+ HInstruction* array_get1 = new (GetAllocator()) HArrayGet(array,
+ c1,
+ DataType::Type::kInt32,
+ 0);
+
+ HInstruction* bound_type = new (GetAllocator()) HBoundType(array);
+ HInstruction* array_get2 = new (GetAllocator()) HArrayGet(bound_type,
+ c1,
+ DataType::Type::kInt32,
+ 0);
+
+ HInstruction* null_check = new (GetAllocator()) HNullCheck(bound_type, 0);
+ HInstruction* array_get3 = new (GetAllocator()) HArrayGet(null_check,
+ c1,
+ DataType::Type::kInt32,
+ 0);
+
+ HInstruction* inter_addr = new (GetAllocator()) HIntermediateAddress(null_check, c1, 0);
+ HInstruction* array_get4 = new (GetAllocator()) HArrayGet(inter_addr,
+ c1,
+ DataType::Type::kInt32,
+ 0);
+ entry->AddInstruction(array);
+ entry->AddInstruction(array_get1);
+ entry->AddInstruction(bound_type);
+ entry->AddInstruction(array_get2);
+ entry->AddInstruction(null_check);
+ entry->AddInstruction(array_get3);
+ entry->AddInstruction(inter_addr);
+ entry->AddInstruction(array_get4);
+
+ HeapLocationCollector heap_location_collector(graph_);
+ heap_location_collector.VisitBasicBlock(entry);
+
+ // Test that the HeapLocationCollector should be able to tell
+ // that there is only ONE array location, no matter how many
+ // 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.GetArrayAccessHeapLocation(array, c1);
+ size_t loc2 = heap_location_collector.GetArrayAccessHeapLocation(bound_type, c1);
+ size_t loc3 = heap_location_collector.GetArrayAccessHeapLocation(null_check, c1);
+ size_t loc4 = heap_location_collector.GetArrayAccessHeapLocation(inter_addr, c1);
+ ASSERT_TRUE(loc1 != HeapLocationCollector::kHeapLocationNotFound);
+ ASSERT_EQ(loc1, loc2);
+ ASSERT_EQ(loc1, loc3);
+ ASSERT_EQ(loc1, loc4);
+}
+
} // namespace art