Support VecLoad and VecStore in LSA.
Test: test-art-host
Test: test-art-target
Test: load_store_analysis_test
Change-Id: I7d819061ec9ea12f86a926566c3845231fce6e26
diff --git a/compiler/optimizing/load_store_analysis.h b/compiler/optimizing/load_store_analysis.h
index 5a1df45..999026c 100644
--- a/compiler/optimizing/load_store_analysis.h
+++ b/compiler/optimizing/load_store_analysis.h
@@ -102,23 +102,26 @@
class HeapLocation : public ArenaObject<kArenaAllocLSA> {
public:
static constexpr size_t kInvalidFieldOffset = -1;
-
+ // Default value for heap locations which are not vector data.
+ static constexpr size_t kScalar = 1;
// TODO: more fine-grained array types.
static constexpr int16_t kDeclaringClassDefIndexForArrays = -1;
HeapLocation(ReferenceInfo* ref_info,
size_t offset,
HInstruction* index,
+ size_t vector_length,
int16_t declaring_class_def_index)
: ref_info_(ref_info),
offset_(offset),
index_(index),
+ vector_length_(vector_length),
declaring_class_def_index_(declaring_class_def_index),
value_killed_by_loop_side_effects_(true) {
DCHECK(ref_info != nullptr);
DCHECK((offset == kInvalidFieldOffset && index != nullptr) ||
(offset != kInvalidFieldOffset && index == nullptr));
- if (ref_info->IsSingleton() && !IsArrayElement()) {
+ if (ref_info->IsSingleton() && !IsArray()) {
// Assume this location's value cannot be killed by loop side effects
// until proven otherwise.
value_killed_by_loop_side_effects_ = false;
@@ -128,6 +131,7 @@
ReferenceInfo* GetReferenceInfo() const { return ref_info_; }
size_t GetOffset() const { return offset_; }
HInstruction* GetIndex() const { return index_; }
+ size_t GetVectorLength() const { return vector_length_; }
// Returns the definition of declaring class' dex index.
// It's kDeclaringClassDefIndexForArrays for an array element.
@@ -135,7 +139,7 @@
return declaring_class_def_index_;
}
- bool IsArrayElement() const {
+ bool IsArray() const {
return index_ != nullptr;
}
@@ -148,15 +152,26 @@
}
private:
- ReferenceInfo* const ref_info_; // reference for instance/static field or array access.
- const size_t offset_; // offset of static/instance field.
- HInstruction* const index_; // index of an array element.
- const int16_t declaring_class_def_index_; // declaring class's def's dex index.
- bool value_killed_by_loop_side_effects_; // value of this location may be killed by loop
- // side effects because this location is stored
- // into inside a loop. This gives
- // better info on whether a singleton's location
- // value may be killed by loop side effects.
+ // Reference for instance/static field, array element or vector data.
+ ReferenceInfo* const ref_info_;
+ // Offset of static/instance field.
+ // Invalid when this HeapLocation is not field.
+ const size_t offset_;
+ // Index of an array element or starting index of vector data.
+ // Invalid when this HeapLocation is not array.
+ HInstruction* const index_;
+ // Vector length of vector data.
+ // When this HeapLocation is not vector data, it's value is kScalar.
+ const size_t vector_length_;
+ // Declaring class's def's dex index.
+ // Invalid when this HeapLocation is not field access.
+ const int16_t declaring_class_def_index_;
+
+ // Value of this location may be killed by loop side effects
+ // because this location is stored into inside a loop.
+ // This gives better info on whether a singleton's location
+ // value may be killed by loop side effects.
+ bool value_killed_by_loop_side_effects_;
DISALLOW_COPY_AND_ASSIGN(HeapLocation);
};
@@ -218,14 +233,26 @@
return nullptr;
}
- size_t GetArrayAccessHeapLocation(HInstruction* array, HInstruction* index) const {
+ size_t GetFieldHeapLocation(HInstruction* object, const FieldInfo* field) const {
+ DCHECK(object != nullptr);
+ DCHECK(field != nullptr);
+ return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(object)),
+ 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);
- HInstruction* original_ref = HuntForOriginalReference(array);
- ReferenceInfo* ref_info = FindReferenceInfoOf(original_ref);
- return FindHeapLocationIndex(ref_info,
+ DCHECK_GE(vector_length, HeapLocation::kScalar);
+ return FindHeapLocationIndex(FindReferenceInfoOf(HuntForOriginalReference(array)),
HeapLocation::kInvalidFieldOffset,
index,
+ vector_length,
HeapLocation::kDeclaringClassDefIndexForArrays);
}
@@ -242,15 +269,26 @@
}
// Find and return the heap location index in heap_locations_.
+ // NOTE: When heap locations are created, potentially aliasing/overlapping
+ // accesses are given different indexes. This find function also
+ // doesn't take aliasing/overlapping into account. For example,
+ // this function returns three different indexes for:
+ // - ref_info=array, index=i, vector_length=kScalar;
+ // - ref_info=array, index=i, vector_length=2;
+ // - ref_info=array, index=i, vector_length=4;
+ // In later analysis, ComputeMayAlias() and MayAlias() compute and tell whether
+ // these indexes alias.
size_t FindHeapLocationIndex(ReferenceInfo* ref_info,
size_t offset,
HInstruction* index,
+ size_t vector_length,
int16_t declaring_class_def_index) const {
for (size_t i = 0; i < heap_locations_.size(); i++) {
HeapLocation* loc = heap_locations_[i];
if (loc->GetReferenceInfo() == ref_info &&
loc->GetOffset() == offset &&
loc->GetIndex() == index &&
+ loc->GetVectorLength() == vector_length &&
loc->GetDeclaringClassDefIndex() == declaring_class_def_index) {
return i;
}
@@ -315,7 +353,10 @@
return true;
}
- bool CanArrayIndicesAlias(const HInstruction* i1, const HInstruction* i2) const;
+ bool CanArrayElementsAlias(const HInstruction* idx1,
+ const size_t vector_length1,
+ const HInstruction* idx2,
+ const size_t vector_length2) const;
// `index1` and `index2` are indices in the array of collected heap locations.
// Returns the position in the bit vector that tracks whether the two heap
@@ -340,7 +381,7 @@
HeapLocation* loc2 = heap_locations_[index2];
if (loc1->GetOffset() != loc2->GetOffset()) {
// Either two different instance fields, or one is an instance
- // field and the other is an array element.
+ // field and the other is an array data.
return false;
}
if (loc1->GetDeclaringClassDefIndex() != loc2->GetDeclaringClassDefIndex()) {
@@ -350,10 +391,12 @@
if (!CanReferencesAlias(loc1->GetReferenceInfo(), loc2->GetReferenceInfo())) {
return false;
}
- if (loc1->IsArrayElement() && loc2->IsArrayElement()) {
- HInstruction* array_index1 = loc1->GetIndex();
- HInstruction* array_index2 = loc2->GetIndex();
- if (!CanArrayIndicesAlias(array_index1, array_index2)) {
+ if (loc1->IsArray() && loc2->IsArray()) {
+ HInstruction* idx1 = loc1->GetIndex();
+ HInstruction* idx2 = loc2->GetIndex();
+ size_t vector_length1 = loc1->GetVectorLength();
+ size_t vector_length2 = loc2->GetVectorLength();
+ if (!CanArrayElementsAlias(idx1, vector_length1, idx2, vector_length2)) {
return false;
}
ReferenceInfo* ref_info = loc1->GetReferenceInfo();
@@ -383,14 +426,15 @@
HeapLocation* GetOrCreateHeapLocation(HInstruction* ref,
size_t offset,
HInstruction* index,
+ size_t vector_length,
int16_t declaring_class_def_index) {
HInstruction* original_ref = HuntForOriginalReference(ref);
ReferenceInfo* ref_info = GetOrCreateReferenceInfo(original_ref);
size_t heap_location_idx = FindHeapLocationIndex(
- ref_info, offset, index, declaring_class_def_index);
+ ref_info, offset, index, vector_length, declaring_class_def_index);
if (heap_location_idx == kHeapLocationNotFound) {
HeapLocation* heap_loc = new (GetGraph()->GetAllocator())
- HeapLocation(ref_info, offset, index, declaring_class_def_index);
+ HeapLocation(ref_info, offset, index, vector_length, declaring_class_def_index);
heap_locations_.push_back(heap_loc);
return heap_loc;
}
@@ -403,12 +447,19 @@
}
const uint16_t declaring_class_def_index = field_info.GetDeclaringClassDefIndex();
const size_t offset = field_info.GetFieldOffset().SizeValue();
- return GetOrCreateHeapLocation(ref, offset, nullptr, declaring_class_def_index);
+ return GetOrCreateHeapLocation(ref,
+ offset,
+ nullptr,
+ HeapLocation::kScalar,
+ declaring_class_def_index);
}
- void VisitArrayAccess(HInstruction* array, HInstruction* index) {
- GetOrCreateHeapLocation(array, HeapLocation::kInvalidFieldOffset,
- index, HeapLocation::kDeclaringClassDefIndexForArrays);
+ void VisitArrayAccess(HInstruction* array, HInstruction* index, size_t vector_length) {
+ GetOrCreateHeapLocation(array,
+ HeapLocation::kInvalidFieldOffset,
+ index,
+ vector_length,
+ HeapLocation::kDeclaringClassDefIndexForArrays);
}
void VisitInstanceFieldGet(HInstanceFieldGet* instruction) OVERRIDE {
@@ -456,12 +507,30 @@
// since we cannot accurately track the fields.
void VisitArrayGet(HArrayGet* instruction) OVERRIDE {
- VisitArrayAccess(instruction->InputAt(0), instruction->InputAt(1));
+ HInstruction* array = instruction->InputAt(0);
+ HInstruction* index = instruction->InputAt(1);
+ VisitArrayAccess(array, index, HeapLocation::kScalar);
CreateReferenceInfoForReferenceType(instruction);
}
void VisitArraySet(HArraySet* instruction) OVERRIDE {
- VisitArrayAccess(instruction->InputAt(0), instruction->InputAt(1));
+ HInstruction* array = instruction->InputAt(0);
+ HInstruction* index = instruction->InputAt(1);
+ VisitArrayAccess(array, index, 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());
+ CreateReferenceInfoForReferenceType(instruction);
+ }
+
+ void VisitVecStore(HVecStore* instruction) OVERRIDE {
+ HInstruction* array = instruction->InputAt(0);
+ HInstruction* index = instruction->InputAt(1);
+ VisitArrayAccess(array, index, instruction->GetVectorLength());
has_heap_stores_ = true;
}