| Index: runtime/vm/intermediate_language.cc
|
| diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
|
| index 7e1986c8bb933a7b781d15b3b83964b2703a854c..d1421dde0e8d78b86f6fa3a6e8336343cbf4f336 100644
|
| --- a/runtime/vm/intermediate_language.cc
|
| +++ b/runtime/vm/intermediate_language.cc
|
| @@ -2121,13 +2121,15 @@ RangeBoundary RangeBoundary::UpperBound() const {
|
| }
|
|
|
|
|
| +static bool AreEqualDefinitions(Definition* a, Definition* b) {
|
| + return (a == b) || (!a->AffectedBySideEffect() && a->Equals(b));
|
| +}
|
| +
|
| +
|
| // Returns true if two range boundaries refer to the same symbol.
|
| static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) {
|
| - if (!a.IsSymbol() || !b.IsSymbol()) return false;
|
| - if (a.symbol() == b.symbol()) return true;
|
| -
|
| - return !a.symbol()->AffectedBySideEffect() &&
|
| - a.symbol()->Equals(b.symbol());
|
| + return a.IsSymbol() && b.IsSymbol() &&
|
| + AreEqualDefinitions(a.symbol(), b.symbol());
|
| }
|
|
|
|
|
| @@ -2453,12 +2455,6 @@ static bool IsArrayLength(Definition* defn) {
|
| }
|
|
|
|
|
| -static bool IsLengthOf(Definition* defn, Definition* array) {
|
| - return IsArrayLength(defn) &&
|
| - (defn->AsLoadField()->value()->definition() == array);
|
| -}
|
| -
|
| -
|
| void BinarySmiOpInstr::InferRange() {
|
| // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the
|
| // right and a non-constant on the left.
|
| @@ -2534,7 +2530,7 @@ void BinarySmiOpInstr::InferRange() {
|
| }
|
|
|
|
|
| -bool CheckArrayBoundInstr::IsRedundant() {
|
| +bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) {
|
| // Check that array has an immutable length.
|
| if ((array_type() != kArrayCid) && (array_type() != kImmutableArrayCid)) {
|
| return false;
|
| @@ -2550,13 +2546,21 @@ bool CheckArrayBoundInstr::IsRedundant() {
|
|
|
| RangeBoundary max = CanonicalizeBoundary(index_range->max(),
|
| RangeBoundary::OverflowedMaxSmi());
|
| +
|
| + if (max.Overflowed()) return false;
|
| +
|
| + // Try to compare constant boundaries.
|
| + if (max.UpperBound().value() < length.LowerBound().value()) {
|
| + return true;
|
| + }
|
| +
|
| + length = CanonicalizeBoundary(length, RangeBoundary::OverflowedMaxSmi());
|
| + if (length.Overflowed()) return false;
|
| +
|
| + // Try symbolic comparison.
|
| do {
|
| - if (max.IsSymbol() &&
|
| - (max.offset() < 0) &&
|
| - IsLengthOf(max.symbol(), array()->definition())) {
|
| - return true;
|
| - }
|
| - } while (CanonicalizeMaxBoundary(&max));
|
| + if (DependOnSameSymbol(max, length)) return max.offset() < length.offset();
|
| + } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length));
|
|
|
| // Failed to prove that maximum is bounded with array length.
|
| return false;
|
|
|