Index: src/compiler/operation-typer.cc |
diff --git a/src/compiler/operation-typer.cc b/src/compiler/operation-typer.cc |
index 9198f4b9a9132ca870f43f2be92fdd42c3b26cfc..005b4b686c150eef0f9e6f28912612f5ac274621 100644 |
--- a/src/compiler/operation-typer.cc |
+++ b/src/compiler/operation-typer.cc |
@@ -796,8 +796,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 min_lhs = lhs->Min(); |
+ int32_t max_lhs = lhs->Max(); |
+ uint32_t min_rhs = rhs->Min(); |
+ uint32_t max_rhs = rhs->Max(); |
+ if (max_rhs > 31) { |
+ // rhs can be larger than the bitmask |
+ max_rhs = 31; |
+ min_rhs = 0; |
+ } |
+ |
+ if (max_lhs > (kMaxInt >> max_rhs) || min_lhs < (kMinInt >> max_rhs)) { |
+ // overflow possible |
+ return Type::Signed32(); |
+ } |
+ |
+ double min = |
+ std::min(static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << min_rhs), |
+ static_cast<int32_t>(static_cast<uint32_t>(min_lhs) << max_rhs)); |
+ double max = |
+ std::max(static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << min_rhs), |
+ static_cast<int32_t>(static_cast<uint32_t>(max_lhs) << max_rhs)); |
+ |
+ if (max == kMaxInt && min == kMinInt) return Type::Signed32(); |
+ return Type::Range(min, max, zone()); |
} |
Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) { |
@@ -809,33 +836,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 min_lhs = lhs->Min(); |
+ int32_t max_lhs = lhs->Max(); |
+ uint32_t min_rhs = rhs->Min(); |
+ uint32_t max_rhs = rhs->Max(); |
+ if (max_rhs > 31) { |
+ // rhs can be larger than the bitmask |
+ max_rhs = 31; |
+ min_rhs = 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(min_lhs >> min_rhs, min_lhs >> max_rhs); |
+ double max = std::max(max_lhs >> min_rhs, max_lhs >> max_rhs); |
+ |
if (max == kMaxInt && min == kMinInt) return Type::Signed32(); |
return Type::Range(min, max, zone()); |
} |