[vm/compiler] Ensure aliasing between *[C|S] and X[C'|S'] for S < S'.
Previously when computing aliasing during load propagation we only propagated aliasing from X[C'|S'] to *[C''|S''] for S' < S''. The code incorrectly assumed that this propagation is symmetric (which it is not) and expected that *[C|S] would be cross aliased with X[C'|S'] when *[C|S] is visited. Now we split symmetric and non-symmetric parts of the aliasing computation: X[C'|S'] propagates aliasing to X[C''|S''] for S' < S'' - which is symmetric. Separately if X is an aliased instance we propagate aliasing from X[C'|S'] to *[C|S] for all sizes S. Change-Id: Iccd4c73a18ffd3f60fd179df43a6b117e0844b64 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101281 Commit-Queue: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
fb7137ba6f
commit
836c04f3d2
@@ -310,6 +310,23 @@ class Place : public ValueObject {
|
||||
RoundByteOffset(to, index_constant_));
|
||||
}
|
||||
|
||||
// Given alias X[ByteOffs|S], smaller element size S' and index from 0 to
|
||||
// S/S' - 1 return alias X[ByteOffs + S'*index|S'] - this is the byte offset
|
||||
// of a smaller typed array element which is contained within this typed
|
||||
// array element.
|
||||
// For example X[8|kInt32] contains inside X[8|kInt16] (index is 0) and
|
||||
// X[10|kInt16] (index is 1).
|
||||
Place ToSmallerElement(ElementSize to, intptr_t index) const {
|
||||
ASSERT(kind() == kConstantIndexed);
|
||||
ASSERT(element_size() != kNoSize);
|
||||
ASSERT(element_size() > to);
|
||||
ASSERT(index >= 0);
|
||||
ASSERT(index <
|
||||
ElementSizeMultiplier(element_size()) / ElementSizeMultiplier(to));
|
||||
return Place(ElementSizeBits::update(to, flags_), instance_,
|
||||
ByteOffsetToSmallerElement(to, index, index_constant_));
|
||||
}
|
||||
|
||||
intptr_t id() const { return id_; }
|
||||
|
||||
Kind kind() const { return KindBits::decode(flags_); }
|
||||
@@ -548,6 +565,12 @@ class Place : public ValueObject {
|
||||
return offset & ~(ElementSizeMultiplier(size) - 1);
|
||||
}
|
||||
|
||||
static intptr_t ByteOffsetToSmallerElement(ElementSize size,
|
||||
intptr_t index,
|
||||
intptr_t base_offset) {
|
||||
return base_offset + index * ElementSizeMultiplier(size);
|
||||
}
|
||||
|
||||
class KindBits : public BitField<uword, Kind, 0, 3> {};
|
||||
class RepresentationBits
|
||||
: public BitField<uword, Representation, KindBits::kNextBit, 11> {};
|
||||
@@ -890,13 +913,42 @@ class AliasedSet : public ZoneAllocated {
|
||||
|
||||
// X[C|S] aliases with X[RoundDown(C, S')|S'] and likewise
|
||||
// *[C|S] aliases with *[RoundDown(C, S')|S'].
|
||||
const Place larger_alias =
|
||||
alias->ToLargerElement(static_cast<Place::ElementSize>(i));
|
||||
CrossAlias(alias, larger_alias);
|
||||
if (has_aliased_instance) {
|
||||
// If X is an aliased instance then X[C|S] aliases
|
||||
// with *[RoundDown(C, S')|S'].
|
||||
CrossAlias(alias, larger_alias.CopyWithoutInstance());
|
||||
CrossAlias(alias, alias->ToLargerElement(
|
||||
static_cast<Place::ElementSize>(i)));
|
||||
}
|
||||
|
||||
if (has_aliased_instance) {
|
||||
// If X is an aliased instance then X[C|S] aliases *[C'|S'] for all
|
||||
// related combinations of C' and S'.
|
||||
// Caveat: this propagation is not symmetric (we would not know
|
||||
// to propagate aliasing from *[C'|S'] to X[C|S] when visiting
|
||||
// *[C'|S']) and thus we need to handle both element sizes smaller
|
||||
// and larger than S.
|
||||
const Place no_instance_alias = alias->CopyWithoutInstance();
|
||||
for (intptr_t i = Place::kInt8; i <= Place::kLargestElementSize;
|
||||
i++) {
|
||||
// Skip element sizes that a guaranteed to have no
|
||||
// representatives.
|
||||
if (!typed_data_access_sizes_.Contains(alias->element_size())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto other_size = static_cast<Place::ElementSize>(i);
|
||||
if (other_size > alias->element_size()) {
|
||||
// X[C|S] aliases all larger elements which cover it:
|
||||
// *[RoundDown(C, S')|S'] for S' > S.
|
||||
CrossAlias(alias,
|
||||
no_instance_alias.ToLargerElement(other_size));
|
||||
} else if (other_size < alias->element_size()) {
|
||||
// X[C|S] aliases all sub-elements of smaller size:
|
||||
// *[C+j*S'|S'] for S' < S and j from 0 to S/S' - 1.
|
||||
const auto num_smaller_elements =
|
||||
1 << (alias->element_size() - other_size);
|
||||
for (intptr_t j = 0; j < num_smaller_elements; j++) {
|
||||
CrossAlias(alias,
|
||||
no_instance_alias.ToSmallerElement(other_size, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user