| Index: runtime/vm/intermediate_language.cc
|
| diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
|
| index 3faaeedc1789330d4dc67c1d02052dacc1b3703c..1daa3b1733a4e0a018a382be4653e155bda9edc1 100644
|
| --- a/runtime/vm/intermediate_language.cc
|
| +++ b/runtime/vm/intermediate_language.cc
|
| @@ -1870,7 +1870,25 @@ void Environment::DeepCopyToOuter(Instruction* instr) const {
|
| }
|
|
|
|
|
| -bool Definition::InferRange() {
|
| +RangeBoundary RangeBoundary::LowerBound() const {
|
| + if (IsConstant()) return *this;
|
| + if (symbol()->range() == NULL) return MinSmi();
|
| + return Add(symbol()->range()->min().LowerBound(),
|
| + RangeBoundary::FromConstant(offset_),
|
| + MinSmi());
|
| +}
|
| +
|
| +
|
| +RangeBoundary RangeBoundary::UpperBound() const {
|
| + if (IsConstant()) return *this;
|
| + if (symbol()->range() == NULL) return MaxSmi();
|
| + return Add(symbol()->range()->max().UpperBound(),
|
| + RangeBoundary::FromConstant(offset_),
|
| + MaxSmi());
|
| +}
|
| +
|
| +
|
| +bool Definition::InferRange(RangeOperator op) {
|
| ASSERT(GetPropagatedCid() == kSmiCid); // Has meaning only for smis.
|
| if (range_ == NULL) {
|
| range_ = Range::Unknown();
|
| @@ -1880,7 +1898,7 @@ bool Definition::InferRange() {
|
| }
|
|
|
|
|
| -bool ConstantInstr::InferRange() {
|
| +bool ConstantInstr::InferRange(RangeOperator op) {
|
| ASSERT(value_.IsSmi());
|
| if (range_ == NULL) {
|
| intptr_t value = Smi::Cast(value_).Value();
|
| @@ -1892,25 +1910,7 @@ bool ConstantInstr::InferRange() {
|
| }
|
|
|
|
|
| -RangeBoundary RangeBoundary::LowerBound() const {
|
| - if (IsConstant()) return *this;
|
| - if (symbol()->range() == NULL) return MinSmi();
|
| - return Add(symbol()->range()->min().LowerBound(),
|
| - RangeBoundary::FromConstant(offset_),
|
| - MinSmi());
|
| -}
|
| -
|
| -
|
| -RangeBoundary RangeBoundary::UpperBound() const {
|
| - if (IsConstant()) return *this;
|
| - if (symbol()->range() == NULL) return MaxSmi();
|
| - return Add(symbol()->range()->max().UpperBound(),
|
| - RangeBoundary::FromConstant(offset_),
|
| - MaxSmi());
|
| -}
|
| -
|
| -
|
| -bool ConstraintInstr::InferRange() {
|
| +bool ConstraintInstr::InferRange(RangeOperator op) {
|
| Range* value_range = value()->definition()->range();
|
|
|
| // Compute intersection of constraint and value ranges.
|
| @@ -1922,15 +1922,13 @@ bool ConstraintInstr::InferRange() {
|
| }
|
|
|
|
|
| -bool PhiInstr::InferRange() {
|
| +bool PhiInstr::InferRange(RangeOperator op) {
|
| RangeBoundary new_min;
|
| RangeBoundary new_max;
|
|
|
| - bool has_inputs_without_range = false;
|
| for (intptr_t i = 0; i < InputCount(); i++) {
|
| Range* input_range = InputAt(i)->definition()->range();
|
| if (input_range == NULL) {
|
| - has_inputs_without_range = true;
|
| continue;
|
| }
|
|
|
| @@ -1949,23 +1947,25 @@ bool PhiInstr::InferRange() {
|
|
|
| ASSERT(new_min.IsUnknown() == new_max.IsUnknown());
|
| if (new_min.IsUnknown()) {
|
| - ASSERT(range_ == NULL);
|
| + range_ = Range::Unknown();
|
| return false;
|
| }
|
|
|
| - if ((range_ != NULL) && !has_inputs_without_range_) {
|
| - // If phi's range is growing widen it in the direction of growth to
|
| - // speedup convergence.
|
| + if (op == Definition::kRangeWiden) {
|
| + // Apply widening operator.
|
| new_min = RangeBoundary::WidenMin(range_->min(), new_min);
|
| new_max = RangeBoundary::WidenMax(range_->max(), new_max);
|
| + } else if (op == Definition::kRangeNarrow) {
|
| + // Apply narrowing operator.
|
| + new_min = RangeBoundary::NarrowMin(range_->min(), new_min);
|
| + new_max = RangeBoundary::NarrowMax(range_->max(), new_max);
|
| }
|
| - has_inputs_without_range_ = has_inputs_without_range;
|
|
|
| return Range::Update(&range_, new_min, new_max);
|
| }
|
|
|
|
|
| -bool BinarySmiOpInstr::InferRange() {
|
| +bool BinarySmiOpInstr::InferRange(RangeOperator op) {
|
| Range* left_range = left()->definition()->range();
|
| Range* right_range = right()->definition()->range();
|
|
|
| @@ -2010,6 +2010,12 @@ bool BinarySmiOpInstr::InferRange() {
|
|
|
| ASSERT(!new_min.IsUnknown() && !new_max.IsUnknown());
|
| set_overflow(new_min.Overflowed() || new_max.Overflowed());
|
| +
|
| + if (op == Definition::kRangeNarrow) {
|
| + new_min = new_min.Clamp();
|
| + new_max = new_max.Clamp();
|
| + }
|
| +
|
| return Range::Update(&range_, new_min, new_max);
|
| }
|
|
|
|
|