Chromium Code Reviews| Index: src/compiler/operation-typer.cc |
| diff --git a/src/compiler/operation-typer.cc b/src/compiler/operation-typer.cc |
| index 4295a22287f1b24939ecb999358e1032170bc53b..598d334c30896b5314da22dfeef9225ad5a451a1 100644 |
| --- a/src/compiler/operation-typer.cc |
| +++ b/src/compiler/operation-typer.cc |
| @@ -793,8 +793,35 @@ Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) { |
| DCHECK(lhs->Is(Type::Number())); |
| DCHECK(rhs->Is(Type::Number())); |
| - // TODO(turbofan): Infer a better type here. |
| - return Type::Signed32(); |
| + if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None(); |
| + |
| + lhs = NumberToInt32(lhs); |
| + rhs = NumberToUint32(rhs); |
| + |
| + int32_t minLhs = lhs->Min(); |
|
Jarin
2016/11/21 10:34:59
Style nit: minLhs -> min_lhs.
|
| + int32_t maxLhs = lhs->Max(); |
| + uint32_t maxRhs = rhs->Max(); |
| + uint32_t minRhs = rhs->Min(); |
| + if (maxRhs > 31) { |
| + // rhs can be larger than the bitmask |
| + maxRhs = 31; |
| + minRhs = 0; |
| + } |
| + |
| + if (maxLhs > (kMaxInt >> maxRhs) || minLhs < (kMinInt >> maxRhs)) { |
| + // overflow possible |
| + return Type::Signed32(); |
| + } |
| + |
| + double min = |
| + std::min(static_cast<int32_t>(static_cast<uint32_t>(minLhs) << minRhs), |
| + static_cast<int32_t>(static_cast<uint32_t>(minLhs) << maxRhs)); |
| + double max = |
| + std::max(static_cast<int32_t>(static_cast<uint32_t>(maxLhs) << minRhs), |
| + static_cast<int32_t>(static_cast<uint32_t>(maxLhs) << maxRhs)); |
| + |
| + if (max == kMaxInt && min == kMinInt) return Type::Signed32(); |
| + return Type::Range(min, max, zone()); |
| } |
| Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) { |
| @@ -806,33 +833,18 @@ Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) { |
| lhs = NumberToInt32(lhs); |
| rhs = NumberToUint32(rhs); |
| - double min = kMinInt; |
| - double max = kMaxInt; |
| - if (lhs->Min() >= 0) { |
| - // Right-shifting a non-negative value cannot make it negative, nor larger. |
| - min = std::max(min, 0.0); |
| - max = std::min(max, lhs->Max()); |
| - if (rhs->Min() > 0 && rhs->Max() <= 31) { |
| - max = static_cast<int>(max) >> static_cast<int>(rhs->Min()); |
| - } |
| + int32_t minLhs = lhs->Min(); |
| + int32_t maxLhs = lhs->Max(); |
| + uint32_t maxRhs = rhs->Max(); |
| + uint32_t minRhs = rhs->Min(); |
| + if (maxRhs > 31) { |
| + // rhs can be larger than the bitmask |
| + maxRhs = 31; |
| + minRhs = 0; |
| } |
| - if (lhs->Max() < 0) { |
| - // Right-shifting a negative value cannot make it non-negative, nor smaller. |
| - min = std::max(min, lhs->Min()); |
| - max = std::min(max, -1.0); |
| - if (rhs->Min() > 0 && rhs->Max() <= 31) { |
| - min = static_cast<int>(min) >> static_cast<int>(rhs->Min()); |
| - } |
| - } |
| - if (rhs->Min() > 0 && rhs->Max() <= 31) { |
| - // Right-shifting by a positive value yields a small integer value. |
| - double shift_min = kMinInt >> static_cast<int>(rhs->Min()); |
| - double shift_max = kMaxInt >> static_cast<int>(rhs->Min()); |
| - min = std::max(min, shift_min); |
| - max = std::min(max, shift_max); |
| - } |
| - // TODO(jarin) Ideally, the following micro-optimization should be performed |
| - // by the type constructor. |
| + double min = std::min(minLhs >> minRhs, minLhs >> maxRhs); |
| + double max = std::max(maxLhs >> minRhs, maxLhs >> maxRhs); |
| + |
| if (max == kMaxInt && min == kMinInt) return Type::Signed32(); |
| return Type::Range(min, max, zone()); |
| } |